::before and ::after Pseudo‑Elements in CSS

I realise that this type of article is perhaps a little basic amongst the type of people likely to visit my blog in the first place. However, working back over some basic CSS principles with a new junior developer who has joined our team reminded me that, sometimes, these principles get missed, or forgotten, or just aren't covered in enough detail at your average code boot camp. So, for posterity's sake, I wanted to write today about the ::before and ::after pseudo‑elements.
A brief note about :: vs. :
A brief aside quickly before we begin: the more eagle‑eyed amongst you may notice that I'm using two colons when speaking about these pseudo‑elements (e.g.: ::before) rather than the single‑colon mnemonic you might be familiar with (e.g.: :before). I've gone into this difference, and why I'm using :: here, in much more detail in a previous article. CSS3 introduced the double‑colon notation to distinguish pseudo‑elements from pseudo‑classes. Browsers still accept the older single‑colon forms of before and after for compatibility; I use two colons here to make the distinction clear.
Introduction
With that out of the way, let's begin. In CSS, the ::before and ::after pseudo‑elements offer a powerful way to add (or inject) content before or after an element's main content area without changing the underlying HTML. These pseudo‑elements, especially when combined with other CSS tools such as pseudo‑classes like :hover, offer us a way to enhance the functionality and interactivity of our websites and applications.
What Are the ::before and ::after Pseudo‑Elements?
As front‑end developers, we use pseudo‑elements to insert styled content into the user's interface without the need to include it in the document's HTML. More specifically, the ::before and ::after pseudo‑elements allow us to insert content either directly before or after the selected element's content.
Basic Usage of ::before and ::after
In order to use either ::before or ::after, we also need to include the content property. This dictates what will actually be rendered within the pseudo‑element, and without it, nothing will be displayed at all.
Here's a brief example where we inject emojis before and after a title:
h1::before {
content: '🌟 ';
color: gold;
}
h1::after {
content: ' ✨';
color: gold;
}With the markup <h1>Lorem ipsum</h1>, the CSS above will result in the user seeing:
🌟 Lorem Ipsum ✨
Practical Applications
Decorative Elements
One of the most common uses for ::before and ::after is to add decorative content, for example, stylised bullet points, icons, or visual separators.
As an example, this CSS will add large, light grey quote marks before and after a blockquote element:
blockquote::before {
content: '“';
font-size: 2rem;
color: #aaa;
}
blockquote::after {
content: '”';
font-size: 2rem;
color: #aaa;
}Creating a Clearfix
With the widespread adoption of flex and grid, this isn't as relevant as it once was. However, in the world of CSS floats, you would often find a situation where you needed to 'clear' a float, which ensures any elements following the floated element on the page fall beneath it.
The clearfix goes on the container of the floated children. Its after pseudo‑element clears those floats, allowing the container to extend beneath them. In this example, display: table creates a CSS table box; it does not add an HTML table element:
.container::after {
content: '';
display: table;
clear: both;
}Combining ::before and ::after with Pseudo‑Classes
Using ::before and ::after alongside pseudo‑classes like :hover can allow us to develop quite intricate and interactive effects that respond to a user's actions. I've previously chatted about how pseudo‑classes like :hover work, but combining them with pseudo‑elements can make your interfaces all the more dynamic.
For example:
button::after {
content: ' (Click me!)';
opacity: 0;
transition: opacity 0.3s ease;
}
button:hover::after {
opacity: 1;
}Here, when a user hovers their mouse over a button, some additional text ("Click me!") fades into view, offering the user some visual feedback and an additional prompt to click the button.
Common Pitfalls and Tips
The content Property
This is actually the one that prompted me to write this in the first place. If you do not include a content property, then it will not render at all. If you just want to style the pseudo‑element without including text within it, then you'll need to include content: "".
div::before {
content: '';
display: block;
width: 100%;
height: 5px;
background-color: #000;
}Positioning and Layout
By default, ::before and ::after are inline elements. If you intend to use them for more complex elements, then you'll often need to change their display or position properties. I often find myself doing both...
Best Practices for Using ::before and ::after
Only Use Them for Non‑Essential Content
Keep essential information in the HTML. Screen readers may announce generated content, but support varies between browser and assistive‑technology combinations. Decorative content still needs care too: text added through CSS is not automatically hidden from screen readers.
Combine with Transitions
When using ::before and ::after with :hover or other pseudo‑classes, adding transitions can create a smoother user experience. Otherwise, they will just appear and disappear, potentially shunting the content around them.
Wrapping Up
The :before and :after pseudo‑elements are fairly basic, but powerful tools which enable us ‑ as front‑end developers ‑ to add content and style elements outside of the restrictions of the HTML markup.
Whether we're adding decorative touches, creating interactive elements with :hover, or managing content flow, these pseudo‑elements are invaluable for modern web development.