Pseudo-Classes
Pseudo-classes style elements based on their state or position: a button being hovered, a field being focused, every second row in a table.
On this page · 5 min · Intermediate
On this page
- Learning objectives
- Explanation
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Intermediate
- Updated
- Oct 28, 2026
Learning objectives#
- Style interaction states: hover, focus, active
- Style form states: checked, disabled, invalid
- Select by position with :first-child and :nth-child()
- Use :not(), :is() and :has()
Explanation#
A pseudo-class starts with a single colon and describes a state: a:hover, input:focus, button:disabled.
Interaction: :hover (mouse over), :focus (selected for typing), :focus-visible (focused by keyboard), :active (being pressed).
Structure: :first-child, :last-child, :nth-child(2), :nth-child(odd), :nth-child(3n) select by position among siblings.
Logic: :not(.active) excludes; :is(h1, h2, h3) groups; :has(img) selects a parent that contains an image — CSS’s long-awaited “parent selector”.
Link order matters: :link, :visited, :hover, :active (remember “LoVe HAte”).
Code example: States and positions#
<style>
body { font-family: sans-serif; }
.btn { padding: 8px 16px; border: 0; border-radius: 6px; background: #2965f1; color: white; cursor: pointer; }
.btn:hover { background: #1d4ed8; }
.btn:active { transform: scale(0.97); }
.btn:focus-visible { outline: 3px solid #f59e0b; outline-offset: 2px; }
.btn:disabled { background: #94a3b8; cursor: not-allowed; }
tr:nth-child(even) { background: #f1f5f9; }
li:first-child { font-weight: bold; }
li:not(:last-child) { border-bottom: 1px solid #ddd; }
input:checked + label { color: #16a34a; text-decoration: line-through; }
.card:has(input:checked) { background: #dcfce7; }
.card { padding: 6px; border-radius: 6px; }
</style>
<button class="btn">Hover / Tab / Click me</button>
<button class="btn" disabled>Disabled</button>
<table><tr><td>Row 1</td></tr><tr><td>Row 2</td></tr><tr><td>Row 3</td></tr><tr><td>Row 4</td></tr></table>
<ul><li>First item</li><li>Second</li><li>Last</li></ul>
<div class="card"><input type="checkbox" id="t1"><label for="t1">Buy milk</label></div>
A button that darkens on hover, shrinks when pressed and shows an orange ring on keyboard focus; a greyed disabled button; striped table rows; a bold first list item; and a to-do that turns green and crossed out when ticked.
Step-by-step explanation#
- :hover, :active and :focus-visible give the button three interactive states.
- :disabled styles the button with the disabled attribute.
- tr:nth-child(even) stripes every second row.
- li:not(:last-child) adds a divider under every item except the last.
- input:checked + label styles the label next to a ticked checkbox.
- .card:has(input:checked) styles the parent card when its checkbox is ticked.
Real-world use case#
Buttons, links, form fields, zebra-striped tables, completed to-do items and active menu items are all styled with pseudo-classes.
Common mistakes#
Touch screens and keyboards do not hover. Always style :focus-visible too.
p:nth-child(2) means “the 2nd child, if it is a p”. p:nth-of-type(2) means “the 2nd p”.
If :hover comes before :visited, visited links never show the hover style. Use LoVe HAte order.
Best practices#
- Give every interactive element hover, focus-visible and active states
- Use :disabled and cursor: not-allowed for disabled controls
- Use :has() for parent styling instead of extra JavaScript
- Prefer :focus-visible over :focus for outlines
Remember this#
One colon = state (:hover). Two colons = a made-up part (::before).
LoVe HAte: :link → :visited → :hover → :active.
:nth-child(odd) / (even) = instant zebra stripes.
Practice exercise#
Your task: Make every third list item red and give text inputs a blue border when focused.
Need a hint?
Show solution
li:nth-child(3n) { color: red; }
input[type="text"]:focus { border: 2px solid blue; outline: none; }
Mini quiz#
Which selects every odd row of a table?
Want more? Practise all CSS MCQs · CSS interview questions
My notes#
Saved in this browser.