Skip to content
CSS

CSS Pseudo-Elements Masterclass

Go beyond ::before and ::after — decorative elements, counters, selections, and creative techniques.

stellae.design

8 min read

Introduction

CSS pseudo-elements let you style specific parts of an element or inject content without changing HTML. ::before and ::after are most known, but there are several more.

Essential for decorative elements, custom list markers, text selections, and creative techniques — all without touching the DOM.

This guide covers the full range with practical production patterns.


Key Concepts

::before and ::after

css
.badge::before {
  content: "";
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--status-color);
  margin-inline-end: 0.5rem;
}
.external-link::after { content: " ↗"; font-size: 0.75em; }

::marker

css
li::marker {
  color: var(--color-primary);
  font-weight: 700;
}

::selection and ::placeholder

css
::selection { background: oklch(0.7 0.15 250 / 0.3); }
input::placeholder { color: var(--text-muted); font-style: italic; }

Practical Examples

1. Decorative Underline

css
.section-title::after {
  content: "";
  display: block;
  width: 3rem; height: 3px;
  background: var(--color-primary);
  margin-top: 0.5rem;
}

2. Image Overlay

css
.card-image::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);
  pointer-events: none;
}

3. Tooltip Arrow

css
.tooltip::before {
  content: "";
  position: absolute;
  top: 100%; left: 50%;
  translate: -50% 0;
  border: 6px solid transparent;
  border-top-color: var(--surface);
}

Best Practices

  • Always set content (even to '') — won't render without it.
  • Use for decorative content only — not accessible text.
  • Pseudo-elements are children, not siblings.
  • Use ::marker for list styling instead of ::before hacks.
  • Add pointer-events: none to overlays.
  • Can't add to void/replaced elements (img, input, br).

Common Pitfalls

  1. Adding to <img>, <input>, <br> — void elements don't support them.
  2. Forgetting content: '' — element won't render.
  3. Using for accessible content — screen readers are inconsistent.
  4. Not setting display: block/inline-block for width/height.

Browser Support

::before/::after: universal. ::marker: Chrome 86+, Safari 11.1+, Firefox 68+. ::selection/::placeholder: universal.


CSScss

Was this article helpful?