Skip to content
::before / ::afterIntermediateUsed in 2,842 effects

Layering with ::before and ::after

::before and ::after create generated boxes as the first and last child of an element. They are ideal for decoration that belongs to a component but should not become extra document content: glows, badges, borders, overlays, and animated fills.

Generated content still participates in layout, painting, and stacking. Reliable pseudo-elements therefore need an explicit content value, a positioning context, and deliberate rules for clipping and pointer events.

Create and position the generated box

A pseudo-element is not rendered until content creates it. For purely visual layers, use content: "". Give the parent position: relative and the pseudo-element position: absolute; inset: 0 then covers the parent's padding box.

Use pointer-events: none on decoration placed above interactive content. Without it, a transparent overlay can intercept clicks even though visitors cannot see the box.

content
Required for ::before and ::after to generate a box. Keep meaningful text in HTML.
inset
A compact way to set top, right, bottom, and left for absolutely positioned layers.
isolation
Creates a local stacking context so negative layers do not disappear behind unrelated ancestors.
cssA safe overlay foundation
.panel {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: 1rem;
}

.panel::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: linear-gradient(135deg, #2563eb, #a855f7);
  pointer-events: none;
}

Control stacking without surprises

A negative z-index can place a pseudo-element behind its parent, but it may also slip behind an ancestor background. isolation: isolate on the component creates a local stacking context and makes that pattern predictable.

When content must remain above an overlay, position the content wrapper and give it a higher stacking level. Avoid arbitrary values such as 9999; a small local scale is easier to reason about.

Animate borders, fills, and underlines

Because a pseudo-element has its own transform and opacity, it can animate without changing the component's box. A link underline can grow with scaleX, while a button fill can slide under the label using translateX.

Inherit the parent's border-radius whenever the layer reaches an edge. Otherwise colored corners can extend beyond the rounded surface.

cssAn underline that does not reflow text
.link { position: relative; }
.link::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -.2em;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 180ms ease;
}
.link:hover::after,
.link:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left;
}

Keep semantics in the document

Generated content is not a dependable accessibility API. Do not use it for instructions, prices, status messages, or information required to understand an action. Put meaningful content in HTML and reserve pseudo-elements for visual reinforcement.

Pseudo-elements are also unavailable or inconsistent on replaced elements such as img and many form controls. Wrap those elements when you need an extra visual layer.

Live catalog examples

These production examples use ::before / ::after. Open any effect to inspect its complete source and experiment in the browser editor.

Browser support

Support notes refer to stable, unprefixed behavior unless a prefix is explicitly listed.

FeatureBrowsersNote
::before / ::afterAll modern browsersRequires `content` to generate the pseudo-element.
insetAll modern browsersUse physical offsets only when supporting much older browsers.
isolationAll modern browsersUseful for containing blend modes and negative stacking.

Common pitfalls

  • The content declaration is missing

    Add content: "" for a decorative generated box.

  • A negative layer disappears

    Create a local stacking context with isolation: isolate and keep z-index values local.

  • The overlay blocks interaction

    Set pointer-events: none unless the pseudo-element intentionally handles input.

  • Rounded corners leak

    Use border-radius: inherit or clip the component when the layer reaches its edges.

Frequently asked questions

Do pseudo-elements add DOM nodes?
No. They create boxes in the formatting tree, but they are not ordinary HTML elements.
Can I use both on one element?
Yes. They provide two independent generated layers, each with its own layout and stacking rules.
Why does ::before not appear on an image?
Images are replaced elements. Wrap the image and place the pseudo-element on the wrapper.
Can generated content be accessible?
Support varies. Keep essential text and state in semantic HTML.

Related guides

Last updated:

All guides