Pseudo-Classes and Pseudo-Elements
Pseudo-classes target elements in a particular state, like being hovered or the first of their kind, while pseudo-elements target a specific part of an element, like its first letter.
Common Pseudo-Classes
Pseudo-classes use a single colon and select elements based on state or position, without needing extra classes or JavaScript.
a:hover { color: #00cc44; }
input:focus { border-color: #0066ff; }
li:first-child { font-weight: bold; }
li:nth-child(even) { background: #f5f5f5; }
button:disabled { opacity: 0.5; }
Pseudo-Elements
Pseudo-elements use a double colon and let you style a specific portion of an element's content, or insert generated content that isn't part of the actual HTML.
.quote::before { content: '\201C'; }
.quote::after { content: '\201D'; }
p::first-letter { font-size: 2em; float: left; }
Common Mistakes
- Confusing single-colon pseudo-classes with double-colon pseudo-elements (older CSS2 syntax allowed a single colon for both, causing confusion).
- Forgetting that ::before and ::after require a content property, even if it's just an empty string, or they won't render.
- Using :nth-child when you actually mean :nth-of-type, especially in mixed-content containers.
- Overusing generated content for anything that carries real meaning — it isn't accessible to all assistive technology.
Professional Tip
Reserve ::before/::after generated content for purely decorative additions — icons, decorative quotes, visual flourishes — never for content a user actually needs to read, since screen readers handle generated content inconsistently.
Your Turn
Style a list where every even row has a light grey background using :nth-child(even), and add decorative quotation marks around a blockquote using ::before and ::after.
Mini Quiz
What is required for ::before or ::after to actually render on the page?
content declaration, ::before and ::after pseudo-elements will not be generated or displayed at all, even if other styles are applied to them.