Recent chats
ASKGEEZ Q&A GUIDETechnology & devices

Why does CSS content not appear on my pseudo-element?

Quick answer

For ::before or ::after to appear, a matching rule needs a usable content value. Missing content, normal, or none means the pseudo-element is not generated. Try a visible text value, then check that the selector matches and inspect the computed content value for a competing declaration. ::after cannot be applied to replaced elements such as <img>. [S1] [S2] [S3]

LET’S WORK THROUGH IT

The question, the details, the next step.

Question

Why does CSS content not appear on my pseudo-element? I have an ::after rule, but nothing shows.

Geez

Start with the content declaration. A rule for ::before or ::after needs a generated-content value; if content is missing, normal, or none, the pseudo-element is not rendered. [S1] [S2]

Try this small example with an ordinary element:

<span class="label">Draft</span>
.label::after {
  content: " (not final)";
}

For a quick test, use a visible text value. That helps distinguish missing generated content from content that is present but not immediately apparent.

Follow-up question

I added a content value. How can I tell whether I used a suitable element?

Geez

Test the rule on an ordinary element such as a span or div. One specific limitation is that ::after cannot be applied to replaced elements such as <img>. [S2] If your rule targets an image, put a wrapper around it and target the wrapper instead:

<span class="image-wrap"><img src="[image path]" alt="Example"></span>
.image-wrap::after {
  content: "Image note";
}

Here, [image path] is a placeholder to replace in your own page. This example addresses the replaced-element limitation; it does not establish whether other elements or layouts in your project are causing a separate issue.

Follow-up question

My element is a span, but the pseudo-element still does not show. What should I inspect next?

Geez

Check whether the intended selector matches the element, then inspect the computed content value for that pseudo-element. The final property value depends on the declarations that apply and how they rank in the cascade. [S2] [S3]

For example, if the computed value is none, the pseudo-element will not be generated. Look for another applicable content declaration in the styles for that pseudo-element. In your browser’s developer tools, inspect its ::after styles or computed styles and confirm that the selector matches and the winning content value is the one you expect.

The references explain rendering conditions and the cascade, but do not prescribe a complete, browser-specific debugging workflow. Developer-tool labels and layouts can vary.

Follow-up question

Can you give me a short checklist I can use while debugging?

Geez

Work through these checks in order, changing one thing at a time:

  1. Confirm you are using the intended pseudo-element: ::before or ::after.
  2. Temporarily set a visible value, such as content: "TEST";. Missing content, normal, and none do not generate the pseudo-element. [S1] [S2]
  3. Confirm the selector matches the element you meant to target.
  4. Check whether the target is a replaced element, such as <img>; try a wrapper instead. [S2]
  5. Inspect the computed content value and look for another applicable declaration that wins in the cascade. [S3]
  6. If visible test text appears but the original effect does not, restore the intended content value and investigate the styling separately.

Copyable minimal test:

.example::after {
  content: "TEST";
}

Replace .example with a selector that matches an element in your page. Remove the temporary text after testing. This checklist narrows common causes; it cannot identify a project-specific cause without the relevant HTML and CSS.

A practical checklist

  • Confirm you are targeting ::before or ::after on the intended element.

  • Temporarily set content: "TEST" to check whether generated text appears.

  • Verify that the selector matches the element you expect.

  • If the target is an <img>, try a wrapper element instead.

  • Inspect the computed content value and check for competing declarations.

  • Remove temporary test content and restore the intended output.

A few more useful answers

Why does `::after` work on a wrapper but not directly on an image?

The ::after reference says it cannot be applied to replaced elements such as <img>. Targeting a wrapper is a practical way to place generated content adjacent to the image instead. [S2]

What should the computed `content` value tell me?

It can help confirm whether the intended rule wins for the pseudo-element. If another applicable declaration determines the final value, inspect the cascade and the selector that supplied it. [S3]

Sources

References used for this guide.

  1. [S1] MDN: CSS content property requirements and behavior
    developer.mozilla.org · Checked
  2. [S2] MDN: ::after rendering conditions and replaced elements
    developer.mozilla.org · Checked
  3. [S3] MDN: CSS property value processing and the cascade
    developer.mozilla.org · Checked

YOUR QUESTION. YOUR DETAILS.

Let’s work through your situation.

Get a tailored answer or help with your next task. Starts at $1, with a quote before you pay.

Ask your own question
← Back to Geez at Work