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.

More CSS articles