Skip to content

CSS Tutorial CSS Pseudo-elements

CSS ::before and ::after

Lesson 123 of 182 2 min read By Deepak Paswan Updated Oct 4, 2026

::before and ::after create a virtual element as the first or last child of the selected element. You use them to add decoration without adding to your HTML.

index.html
HTML
<style>
  .price::before { content: "$"; color: #888; }
  .new::after { content: " NEW"; background: #d94a00; color: #fff; font-size: 11px; padding: 2px 6px; border-radius: 4px; }
</style>
<p class="price">14.00</p>
<p class="new">The Slow Garden</p>

The content property is required

Without content, the pseudo-element does not exist. Even an empty one needs it:

style.css
PHP
.thing::before { content: ""; }

content can be:

  • a string: content: "→ "
  • empty: content: "" (for shapes and decoration)
  • the value of an HTML attribute: content: attr(href)
  • a counter: content: counter(step)
index.html
HTML
<style>
  a::after { content: " (" attr(href) ")"; color: #888; font-size: 0.85em; }
</style>
<p>Read <a href="https://example.com/guide">the guide</a> online.</p>

Pseudo-elements behave like inline elements

By default, a pseudo-element is inline. Set display: block or inline-block to give it size, and position to place it. Many shapes and icons are built this way.

index.html
HTML
<style>
  .quote { position: relative; padding-left: 36px; font-style: italic; }
  .quote::before { content: "“"; position: absolute; left: 0; top: -8px; font-size: 56px; color: #d94a00; }
</style>
<p class="quote">Reading is a way of staying awake.</p>

Accessibility

Generated text is read out by some screen readers, and cannot be selected or translated. Use it only for decoration. Anything that carries meaning should be in the HTML.

warning
Putting real content in ::before
Text such as “Sale!” or a price should be real text. Search engines and many assistive tools may miss it when it only exists in CSS.

Add a small arrow ↗ after every link that starts with https.

Show a possible solution
style.css
PHP
a[href^="https"]::after { content: " ↗"; }