~/
hackweb.dev
CSS Pseudo-classes & Pseudo-elements
Quiz
⌘K
...
~/
/tutorials
/css/css-pseudo-classes/edit
~ Contribute
Suggest a correction or improvement. The author reviews it before it goes live.
Loading...
Comment
0 / 300
Typo
Grammar
Broken link
Clarify
Code
en/tutorials/css/14css-pseudo-classes
Write
Preview
Diff
# CSS Pseudo-classes & Pseudo-elements Pseudo-classes target elements in specific states. Pseudo-elements target specific parts of elements. ## Pseudo-classes ### Link States ```css /* Unvisited link */ a:link { color: blue; } /* Visited link */ a:visited { color: purple; } /* Hover state */ a:hover { color: red; } /* Active (being clicked) */ a:active { color: orange; } /* Focus (keyboard navigation) */ a:focus { outline: 2px solid blue; } ``` **Order:** L-V-H-A (Link, Visited, Hover, Active) ### Input States ```css /* Focus state */ input:focus { border-color: #3498db; outline: none; } /* Disabled */ input:disabled { background-color: #eee; cursor: not-allowed; } /* Enabled */ input:enabled { background-color: white; } /* Required */ input:required { border-left: 3px solid red; } /* Optional */ input:optional { border-left: 3px solid gray; } /* Valid */ input:valid { border-color: green; } /* Invalid */ input:invalid { border-color: red; } /* Checked */ input:checked { accent-color: blue; } /* Placeholder shown */ input:placeholder-shown { color: gray; } ``` ### Structural Pseudo-classes ```css /* First child */ li:first-child { font-weight: bold; } /* Last child */ li:last-child { border-bottom: none; } /* nth-child (position) */ li:nth-child(2) { color: red; } /* nth-child (formula) */ li:nth-child(odd) { background-color: #f5f5f5; } li:nth-child(3n) { font-size: 1.2em; } li:nth-child(3n+1) { color: blue; } /* First of type */ p:first-of-type { font-size: 1.5em; } /* Last of type */ p:last-of-type { margin-bottom: 0; } /* Only child */ .item:only-child { margin: 0 auto; } /* Only of type */ p:only-of-type { font-style: italic; } /* Empty element */ div:empty { display: none; } /* Root element */ :root { font-size: 16px; } /* Not selector */ p:not(.special) { color: gray; } /* Is selector (matches any) */ :is(h1, h2, h3) { line-height: 1.2; } /* Where selector (same as is, lower specificity) */ :where(h1, h2, h3) { margin-bottom: 0.5rem; } /* Has selector (contains) */ div:has(p) { padding: 1rem; } ``` ### Child Pseudo-classes ```css /* Any child */ li:nth-child(n) { /* All items */ } /* First 3 items */ li:nth-child(-n+3) { font-weight: bold; } /* After first 3 items */ li:nth-child(n+4) { color: gray; } /* Last 3 items */ li:nth-last-child(-n+3) { border-bottom: none; } /* Every other item */ li:nth-child(even) { background-color: #f5f5f5; } /* Every third item */ li:nth-child(3n) { margin-left: 20px; } ``` ## Pseudo-elements ### Content Generation ```css /* Before content */ h1::before { content: "★ "; color: gold; } /* After content */ h1::after { content: " ★"; color: gold; } /* With quotes */ blockquote::before { content: open-quote; } blockquote::after { content: close-quote; } /* Empty content (for styling) */ .icon::before { content: ""; display: inline-block; width: 20px; height: 20px; background-image: url('icon.png'); } ``` ### Text Pseudo-elements ```css /* First line */ p::first-line { font-weight: bold; color: #333; } /* First letter */ p::first-letter { font-size: 3em; float: left; line-height: 1; margin-right: 0.1em; } /* Selection */ ::selection { background-color: yellow; color: black; } /* Placeholder */ input::placeholder { color: gray; font-style: italic; } ``` ### Tooltip Example ```css .tooltip { position: relative; display: inline-block; cursor: help; } .tooltip::after { content: attr(data-tooltip); position: absolute; bottom: 125%; left: 50%; transform: translateX(-50%); background-color: #333; color: white; padding: 5px 10px; border-radius: 5px; white-space: nowrap; opacity: 0; visibility: hidden; transition: opacity 0.3s; } .tooltip:hover::after { opacity: 1; visibility: visible; } ``` ```html <span class="tooltip" data-tooltip="This is a tooltip"> Hover me </span> ``` ### Quote Marks ```css q::before { content: open-quote; } q::after { content: close-quote; } blockquote { font-style: italic; border-left: 4px solid #3498db; padding-left: 1rem; margin: 1rem 0; } blockquote::before { content: open-quote; font-size: 2em; color: #ccc; } blockquote::after { content: close-quote; font-size: 2em; color: #ccc; } ``` ## Complete Example: List Styling ```css /* Custom list markers */ ul.custom-list { list-style: none; padding-left: 0; } ul.custom-list li { position: relative; padding-left: 1.5rem; margin-bottom: 0.5rem; } ul.custom-list li::before { content: "✓"; position: absolute; left: 0; color: #27ae60; font-weight: bold; } /* Numbered list with custom format */ ol.custom-list { list-style: none; padding-left: 0; counter-reset: item; } ol.custom-list li { counter-increment: item; padding-left: 2rem; margin-bottom: 0.5rem; } ol.custom-list li::before { content: counter(item) "."; position: absolute; left: 0; font-weight: bold; color: #3498db; } ``` ## Complete Example: Accordion ```css .accordion-item { border: 1px solid #ddd; margin-bottom: 0.5rem; } .accordion-header { display: flex; justify-content: space-between; align-items: center; padding: 1rem; cursor: pointer; background-color: #f5f5f5; } .accordion-header::after { content: "+"; font-size: 1.5rem; font-weight: bold; transition: transform 0.3s; } .accordion-item.active .accordion-header::after { transform: rotate(45deg); } .accordion-content { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; } .accordion-item.active .accordion-content { max-height: 200px; } ``` ## Complete Example: Custom Checkbox ```css .checkbox-wrapper { display: flex; align-items: center; cursor: pointer; } .checkbox-wrapper input { display: none; } .checkbox-mark { width: 20px; height: 20px; border: 2px solid #ccc; border-radius: 4px; margin-right: 10px; position: relative; transition: background-color 0.3s, border-color 0.3s; } .checkbox-wrapper input:checked + .checkbox-mark { background-color: #3498db; border-color: #3498db; } .checkbox-wrapper input:checked + .checkbox-mark::after { content: "✓"; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font-size: 14px; } ``` ```html <label class="checkbox-wrapper"> <input type="checkbox" /> <span class="checkbox-mark"></span> <span>Accept terms</span> </label> ``` ## Best Practices 1. **Use pseudo-classes for states** — Hover, focus, active 2. **Use structural pseudo-classes** — Instead of extra classes 3. **Use pseudo-elements for content** — Decorative content only 4. **Test keyboard navigation** — Focus states are important 5. **Don't use for essential content** — Screen readers may not see it ## Common Mistakes 1. **Wrong order for link states** — L-V-H-A 2. **Using for essential content** — Pseudo-elements aren't accessible 3. **Not providing focus styles** — Keyboard users can't navigate 4. **Overusing :not()** — Can become complex 5. **Forgetting ::before/::after need content** — Even if empty
No changes yet
Reset to original
Submit suggestion
cancel