Pseudo-classes vs Pseudo-elements in CSS
A pseudo-class (:hover) targets an element in a certain state; a pseudo-element (::before) targets a sub-part of an element that doesn't exist in the DOM.
Published September 22, 2026
A pseudo-class (single colon, e.g. :hover, :first-child) selects an existing element based on a state or position that isn't expressible with a plain selector. A pseudo-element (double colon, e.g. ::before, ::first-line) targets a specific sub-part of an element, sometimes generating content that doesn't exist in the actual DOM.
Common causes
- CSS needed a way to style dynamic states (hover, focus, checked) and structural positions (first-child, nth-of-type) without JavaScript, and separately a way to style or inject content around an element's actual content
How to fix it
- Use pseudo-classes like :hover, :focus, :nth-child(), :checked to style based on state or structural position
- Use pseudo-elements like ::before and ::after (commonly with a content property) to insert decorative content without adding extra markup
- Modern CSS uses double colons (::) for pseudo-elements to visually distinguish them from pseudo-classes, though single-colon syntax (:before) is still supported for backward compatibility
Example
.button:hover { background: darkblue; }
.tooltip::after {
content: '\2192';
margin-left: 4px;
}FAQ
Do I need ::before or :before?
Modern browsers accept both for pseudo-elements, but ::before (double colon) is the correct modern syntax and clearly distinguishes it from a pseudo-class like :hover.