CSS ::before vs ::after - When to Use Each Pseudo-element
Choose between CSS ::before and ::after by understanding insertion order, accessibility tree behavior, and common patterns: icons, badges, decorative lines, and clearfix.
Detailed Explanation
The Difference Is Insertion Order
::before inserts a generated child as the first child of the element. ::after inserts one as the last child. Visually, both render in normal flow, so a default ::before appears to the left of (or above) the element's content, and ::after appears to the right (or below).
.tag::before { content: "#"; color: #888; }
.tag::after { content: " ↗"; color: #36c; }
For <span class="tag">design</span> you get: #design ↗.
Pick ::before When …
- The decoration should appear first in reading order (icons, prefixes, bullets).
- You want to push existing content rightward without affecting trailing punctuation.
- Building decorative bars or shapes positioned at the top of an element.
.required-label::before {
content: "* ";
color: red;
}
Pick ::after When …
- The decoration should appear last (trailing icons, badges, "more" indicators).
- Implementing classic clearfix on float layouts.
- Adding a divider beneath a heading.
.external-link::after {
content: " ↗";
font-size: 0.8em;
}
Both Together
For symmetric decorations like quotation marks, use both:
.pull-quote::before { content: "“"; }
.pull-quote::after { content: "”"; }
Accessibility
Generated content from ::before and ::after is included in the accessibility tree by most modern screen readers, but support is uneven. As a rule:
- Decorative-only icons → fine. Reader announcements may be weird but not harmful.
- Critical text (e.g., "Required") → use real DOM, not generated content.
- Use
speak: never;(proposed) or setcontent: ""and use abackground-imagefor purely decorative glyphs.
Specificity
::before and ::after each add (0, 0, 1) — same as a single type selector. They don't replace the original element's specificity; they add to the compound.
Don't Forget the content Property
Without content, neither pseudo-element renders. content: "" (empty string) is the conventional way to make a purely decorative box.
Use Case
Reach for ::before for prefix icons, leading bullets, required-field markers, and decorative top borders. Reach for ::after for trailing icons (external link arrows), "new" badges, clearfix, and underline-style heading decorations. Together they enable CSS-only quotation marks, parentheses, and balanced ornaments.