
::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 prosperity'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. Suffice it to say: double‑colon is the 'correct' use when it comes to pseudo‑elements...
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.
This was achieved by using an ::after pseudo‑element on the floated element to inject a self‑clearing table element like this:
.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.
Understanding Single vs. Double Colons
I already mentioned this at the very start of the article, but you might be wondering whether to use :before or ::before. I've gone into this in great detail in a previous article, but to summarise, CSS3 introduced the double‑colon syntax (::) to clearly differentiate pseudo‑elements from pseudo‑classes like :hover
- Use
::beforeand::afterfor pseudo‑elements. - The single‑colon notation (
:before,:after) is still supported for backward compatibility but should be avoided in modern code for clarity and future‑proofing.
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
Pseudo‑elements are best for decorative or supplementary content, they are not (easily) accessible to screen readers or other assistive technologies. Essential information should always be in the HTML to maintain accessibility.
Combine with Transitions
When using ::before and ::after with :hover or other pseudo‑classes, adding transitions can create a smoother user experiences. 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.
Categories:
Related Articles

Promise.all() vs. Promise.race() in JavaScript. 
Using the CSS :has Pseudo‑Class. Using the CSS
:hasPseudo‑Class
Single or Double Colons in CSS Pseudo‑Elements (:before vs. ::before). Single or Double Colons in CSS Pseudo‑Elements (
:beforevs.::before)
Understanding the :hover Pseudo‑Class in CSS. Understanding the
:hoverPseudo‑Class in CSS
Angular Standalone Components: Do We Still Need Modules? Angular Standalone Components: Do We Still Need Modules?

Understanding File‑System Routing in Next.js. Understanding File‑System Routing in Next.js

How to Use grid in CSS. How to Use
gridin CSS
Generate Parentheses in TypeScript: A Clean Backtracking Walkthrough. Generate Parentheses in TypeScript: A Clean Backtracking Walkthrough

CSS visibility: Hiding Elements Without Affecting Layout. CSS
visibility: Hiding Elements Without Affecting Layout
Memoization in JavaScript: Optimising Function Calls. Memoization in JavaScript: Optimising Function Calls

3Sum Closest in JavaScript: Sorting and Two Pointers. 3Sum Closest in JavaScript: Sorting and Two Pointers

Best Practices for Cross‑Browser Compatibility. Best Practices for Cross‑Browser Compatibility