Warning ::before/::after with no content declaration

Why ::before and ::after don't render at all without a content property, even one that's just set to an empty string.

The validator flags a non-empty ::before or ::after rule block (also matching the older single-colon :before/:after syntax) that has no content declaration anywhere in it.

Example

/* Wrong: never renders, no matter what else is set */
.badge::before {
  background: red;
  width: 8px;
  height: 8px;
}

/* Right */
.badge::before {
  content: "";
  background: red;
  width: 8px;
  height: 8px;
}

Why it matters

Per the CSS spec, ::before and ::after generate a pseudo-element only when their content property computes to something other than none — the default. Without a content declaration at all, content stays at its default of none, and the pseudo-element simply doesn't exist in the render tree — none of the other declarations in the same rule (background, border, width, height, transforms) have anything to apply to. For a purely decorative element with no actual text, content: ""; (an empty string) is the standard way to satisfy this requirement while rendering no text content.

Frequently asked questions

Does content: none also fail to render, same as no content at all?

Yes — content: none is explicitly the same as the property's initial value, so a pseudo-element with either no content declaration or content: none stays unrendered. Any other value, including an empty string, generates it.

Why would this rule ever have no content declaration in real code?

Usually because content: "" got removed during a refactor (e.g. while cleaning up other properties) without noticing it was load-bearing, or because a developer coming from a framework where pseudo-elements aren't a thing assumed a background/width/height was enough on its own.