# The ::before and ::after pseudo-elements in CSS

NicolasBrondinBernard

Author
@NicolasBrondinBernard

Do you know what pseudo-elements are and what they are used for?

Article published on 25/06/2021, last updated on 10/08/2026

When doing web integration, it's sometimes easy to forget that every HTML tag comes with a particular semantic, and even though the right balance isn't easy to find, flooding a page with tags just to manage to integrate a design correctly can have negative consequences, such as:

  • Giving incorrect semantics to digital accessibility tools (screen readers, for example)
  • Drastically increasing the code/content ratio, impacting search engine optimization

To optimize this, we need to separate two types of web objects: content conveying information, and purely decorative illustrations.

For example, a simple shape, an icon, or even an image present to make the interface nice to look at won't need to be present in the form of an element directly integrated into the page, so we'll use two pseudo-elements particularly well suited to this: ::before and ::after.

Pseudo-elements

Pseudo-elements are CSS selectors that allow you to select a "virtual" part of an element that isn't present as an actual element in the HTML page.

Think for example of the ::placeholder selector for a text field

But there are two pseudo-elements, "::before" and "::after", which don't target a part of an existing element, but actually allow you to generate these "virtual" elements only during CSS interpretation.

Once declared, these pseudo-elements are generated as direct children of the element, so they cannot be generated inside simple elements such as or for example.

The syntax

Let's take a fairly simple text element that we'll set up to be easily targeted with our selector, like this:

<p>
  Sa majesté, l'altesse royale :
  <span class="has-crown">Elisabeth II</span>
</p>

Then to generate our pseudo-element, we'll simply need to target it with ::before, assign it content, and it's from that moment that it will be generated and visible.

Note: if you simply want to draw with a pseudo-element without assigning it content, you'll still need to include its content:"" attribute, otherwise it won't be generated or won't be visible.

span.has-crown {
  position: relative;
}

span.has-crown::before {
  content: "";
  position: absolute;
  display: inline-block;
  top:-12px;
  left: -8px;
  transform: rotate(-30deg);
}

Here we're styling our ::before like any other element, keeping in mind that it will be inserted as a child of span.has-crown, so it will only position correctly in absolute if its parent is itself in relative.

And here's the result:

Sa majesté, l'altesse royale : Elisabeth II

If you open your browser's web inspector, you'll see that the pseudo-element is inserted as in the example below:

<p>
  Sa majesté, l'altesse royale :
  <span class="has-crown">
    ::before
    Elisabeth II
  </span>
</p>

::before, ::after, what's the difference?

These two pseudo-elements work in exactly the same way, and the only difference between the two lies in their placement relative to the children of the element in question.

As you might have guessed, ::before is always located before the first child element, and ::after after the last element, no matter whether elements are dynamically removed or inserted via Javascript, ::before and ::after will always surround the other children.

Note that this difference only has an impact when the pseudo-elements are positioned relatively.

Going further

If you want a simple usage example for adding graphic elements with ::before and ::after, I invite you to read my tutorial on advanced CSS in which I use them.

And I invite you to discover the other pseudo-elements available in CSS directly on the Mozilla MDN documentation!


KOBU Agency sur Unsplash

Finished reading this article?
Our newsletter

No spam. Only free content, news, and ever more resources to level up your skills!

Join +1500 developers

Comments (0)

to leave a comment

No comments yet