CSS — Pseudo-classes
A colon changes everything
Pseudo-classes style elements by state or position without touching HTML:
a:hover { color: teal; }
Interaction states
button:hover { background: #0f766e; } /* mouse over */
input:focus { border-color: #0d9488; } /* being typed in */
button:active { transform: scale(0.97); }/* being pressed */
a:visited { color: #6d28d9; } /* already opened */
:hover + :focus-visible + :active on every interactive element is baseline professionalism.
Position among siblings
li:first-child { font-weight: 700; }
li:last-child { border-bottom: none; }
li:nth-child(3) { color: red; } /* exactly the third */
nth-child patterns
li:nth-child(odd) { background: #f8fafc; } /* zebra rows! */
li:nth-child(even) { background: white; }
li:nth-child(3n) { color: teal; } /* every third */
li:nth-child(3n+1) { … } /* 1, 4, 7, … */
The an+b formula: n counts 0,1,2… — covers any rhythm.
Content-state pseudo-classes
/* structural */
:root { --brand: teal; } /* the html element */
:empty { display: none; } /* no children at all */
/* forms */
input:checked + span { font-weight: 700; }
input:disabled { opacity: 0.5; cursor: not-allowed; }
input:required { border-left: 3px solid orange; }
input:focus:invalid { border-color: crimson; }
/* links */
a:any-link { text-decoration-thickness: 2px; }
:checked + sibling is the engine behind pure-CSS switches and tabs.
:not — everything except
.menu li:not(:last-child) {
border-right: 1px solid #ddd;
}
input:not([type="submit"]) {
border: 1px solid #ccc;
}
p:not(.intro):not(.quote) {
margin-bottom: 1em; /* chain for multiple exclusions */
}
Negation keeps CSS honest — style the rule, exclude the exceptions.
:is() — group shorthand
/* instead of repeating: */
header a:hover, main a:hover, footer a:hover { … }
:is(header, main, footer) a:hover {
color: teal;
}
Cleaner, and specificity uses only the most specific argument.
Specificity note
Most pseudo-classes count like a class (0,1,0). Exceptions worth knowing: :not() itself adds nothing (its argument does), :is() takes its highest argument.
Cheat sheet
| Need | Selector |
|---|---|
| Mouse over | :hover |
| Keyboard/current input | :focus / :focus-visible |
| Every 2nd row | :nth-child(even) |
| All but last | :not(:last-child) |
| Checked checkbox effects | :checked + label |
| Disabled button | :disabled |
| Any of several parents | :is(a, b, c) |
Mini Practice
- Full button state set: hover/focus-visible/active.
- Zebra-striped table with nth-child(even).
- Pure-CSS toggle: hidden checkbox +
:checked + label. - Menu dividers via
:not(:last-child)— then add an item and watch it adapt. - Style required vs disabled inputs distinctly.
- Collapse three identical rules into one with
:is().
Next: pseudo-elements →
Related Topics
Frequently Asked Questions about Pseudo-classes
What is Pseudo-classes in CSS?
Pseudo-classes is a fundamental concept in CSS. This lesson explains it step by step with clear examples, making it easy for beginners to understand.
How do I learn Pseudo-classes?
Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Pseudo-classes.
Why is Pseudo-classes important in CSS?
Pseudo-classes is essential for CSS development. Understanding this concept will help you write better code and solve real-world problems more effectively.