Introduction
Pseudo-classes and pseudo-elements extend CSS selectors to target things that don't correspond to a literal HTML tag. Pseudo-classes, written with a single colon like :hover, select elements based on state or position, such as being hovered, focused, or the first child. Pseudo-elements, written with a double colon like ::before, target a specific part of an element or generate content that doesn't exist in the HTML markup itself.
Cricket analogy: A pseudo-class like :hover is like a fielder's state changing to 'alert' when the ball comes near them, based on situation not a fixed role, while a pseudo-element like ::before is like the pitch groundsman adding a boundary rope marking that isn't part of the original ground but is generated for the match.
Syntax
/* Pseudo-classes */
a:hover { color: #f97316; }
input:focus { outline: 2px solid #3b82f6; }
li:first-child { font-weight: bold; }
li:nth-child(odd) { background: #f3f4f6; }
/* Pseudo-elements */
p::first-line { font-variant: small-caps; }
.quote::before {
content: "\201C";
color: #9ca3af;
}
.quote::after {
content: "\201D";
}Explanation
Pseudo-classes such as :hover, :focus, :active, :first-child, :nth-child(), and :not() match elements based on interaction state, document structure, or logical conditions, without requiring any extra markup or classes. Pseudo-elements such as ::before, ::after, ::first-line, and ::placeholder let you style or insert content into a specific sub-part of an element; ::before and ::after require the content property to render anything, even if it's just an empty string used for decorative purposes.
Cricket analogy: :hover, :focus, and :active are like a batter's stance automatically adjusting for a bouncer, a yorker, or a full toss without needing a coach to relabel them each time, while :nth-child() picks every third bowler in a rotation and :not() excludes the wicketkeeper from a fielding drill; ::before and ::after are like adding a virtual boundary marker or replay graphic that only appears once the broadcast explicitly requests it (the content property), even if it's just an empty highlight flash.
Example
.btn {
position: relative;
padding: 10px 20px;
}
.btn::after {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
background: rgba(255, 255, 255, 0.2);
opacity: 0;
transition: opacity 0.2s ease;
}
.btn:hover::after {
opacity: 1;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}Output
The button gains an invisible overlay layer created entirely in CSS via ::after; when the user hovers over the button, that overlay fades to a semi-transparent white highlight, creating a shine effect without any extra HTML elements. If the button has the disabled attribute, the :disabled pseudo-class dims it and changes the cursor to indicate it can't be interacted with.
Cricket analogy: The button's ::after overlay creating a shine effect on hover is like a bat's sweet spot catching stadium lights during a cover drive, purely a visual highlight with no change to the bat itself, while :disabled dimming the button is like a suspended player's name greyed out on the team sheet, unable to be selected.
Key Takeaways
- Pseudo-classes use a single colon (:hover) and target element states or structural position.
- Pseudo-elements use a double colon (::before) and target a sub-part of an element or generated content.
- ::before and ::after require a content property, even an empty string, to be rendered.
- Structural pseudo-classes like :nth-child(2n) and :not() reduce the need for extra classes in markup.
Practice what you learned
1. Which syntax correctly represents a pseudo-element in modern CSS?
2. What property is required for ::before or ::after to actually render?
3. Which pseudo-class selects an element based on its interaction state when a user clicks it?
4. What does li:nth-child(odd) select?
5. Which of these is a pseudo-class rather than a pseudo-element?
Was this page helpful?
You May Also Like
CSS Syntax and Selectors
Learn how CSS rules are structured and how to target HTML elements using the full range of CSS selectors.
CSS Transitions and Animations
Understand how to animate CSS property changes smoothly using transitions and create complex motion with keyframe animations.
CSS Specificity and the Cascade
Learn how the browser decides which CSS rule wins when multiple selectors target the same element.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics