
Single or Double Colons in CSS Pseudo‑Elements (:before vs. ::before)

In CSS, pseudo‑elements like :before and :after (and not to be confused with pseudo‑classes like :has or :hover) are an easy way of adding content and styling to your page without modifying the HTML itself. However, one thing that has come up a few times now is the confusion around whether to use a single colon (:) or a double colon (::), e.g. :before vs. ::before.
Here, I intend to give a quick overview of what a pseudo‑element actually is, the history of these differing notations, and why it's important to use the correct one. Spoiler: double colon is more correct, but it really doesn't make much difference overall.
The History Behind Single and Double Colons
Originally, CSS2 and earlier specifications used a single colon (:) for both pseudo‑classes and pseudo‑elements. This created some ambiguity in the code we wrote, as there was no clear distinction between the two pseudo‑types.
For example:
p:before { content: 'Note: '; color: blue;}p:hover { color: red;}At a glance, the example above can be unclear as to whether :before and :hover are functioning as pseudo‑classes or pseudo‑elements, especially for developers new to CSS. The single‑colon notation made it difficult to distinguish between pseudo‑elements like :before, which inserts content, and pseudo‑classes like :hover, which modifies the visual state of an element.
Explanation of the Ambiguity
If you're a seasoned developer, then this probably doesn't matter, but for developers relatively new to CSS, it becomes a pain point that simply isn't necessary:
Pseudo‑Classes
(e.g.,:hover) apply styles based on an element's state (e.g. when hovered over).Pseudo‑Elements
(e.g.,:before): Insert and style content that is not part of the original document structure.
They are really two quite different concerns within our stylesheets.
The Introduction of Double‑Colon Notation
With the introduction of CSS3, the double‑colon notation (::) was introduced to differentiate pseudo‑elements from pseudo‑classes more clearly:
Pseudo‑classes
use a single colon (:). For example::hover,:focus,:active.Pseudo‑elements
use a double colon (::), like this:::before,::after,::first‑letter.
This change was designed to help developers quickly identify whether a style targets an element's state or a specific part of the element.
Using the same code example as above, it now looks like this:
p::before { content: 'Note: '; color: blue;}p:hover { color: red;}The difference is subtle, but by using ::before, it is more readily obvious that this is a pseudo‑element that inserts content, whilst :hover remains a pseudo‑class modifying the element's state.
The Correct Usage in Modern CSS
In modern CSS, the 'correct' way to use pseudo‑elements is to write them with a double colon (::) to differentiate them from pseudo‑classes.
Why Does This Matter?
Using the double‑colon syntax makes sure that your CSS aligns with the most recent standards and makes your code easier to read and maintain. It signals to both developers and browsers that the style is targeting a pseudo‑element rather than a pseudo‑class and will be more future‑proof because, eventually, browsers may stop supporting single‑colon use for pseudo‑elements.
Browser Compatibility for Double‑Colon Notation
Although most modern browsers fully support the double‑colon notation for pseudo‑elements, you probably should be aware of the pitfalls here in using just the :: notation. Because it generally takes decades for browsers to fully catch‑up with these types of changes, there are some limitations you should be aware of ‑ especially when it comes to compatibility with legacy systems.
Supported Browsers
All major modern browsers support the more modern double‑colon syntax (::before, ::after, etc.), including:
Chrome
(since version 1)Firefox
(since version 3.5)Safari
(since version 1.3)Safari on iOS
(since version 3.2)Opera
(since version 9.5)Edge
(all versions)
Legacy Browsers
The potential issue you may face whilst using :: notation is Internet Explorer, where pseudo‑elements like :before and :after are supported starting from Internet Explorer 5.5. However, they are only recognised with the single‑colon notation (:before, :after) up until Internet Explorer 9, when the browser shifted to double‑colon (::before, ::after).
Fallback for Compatibility
I expect for the majority of developers, this lack of compatibility won't matter. However, if you do need to ensure that your CSS works in these older browsers too, then you should consider using both notations together for compatibility:
p:before,p::before { content: "Note: "; color: blue;}This will provide more modern browsers with the correct ::before notation, whilst older browsers can still interpret the single‑colon version :before. This does ‑ of course ‑ add a little additional weight to your stylesheets.
Key Takeaways
- Pseudo‑classes always use a single colon, e.g.,
:hoveror:focus. - Pseudo‑elements also used to use single‑colons, (e.g.,
:before);however, that changed in CSS3. - Unless supporting IE8 and below, use
::beforeand::afterfor pseudo‑elements to align with modern standards. - Single‑colon (
:) syntax is still supported for compatibility, but ideally, it should be avoided in new code.
Wrapping up
The difference between :before and ::before may seem minor (and in the grand scheme of things, it probably is), but the use of single or double colons does have implications on clarity and for standards compliance in your CSS. You should use double‑colons, and although all modern browsers support both notations, in the future, browsers might start to drop that support for the outdated single‑colon syntax.
Related Articles

CSS box‑sizing: Controlling the Element Box Model. CSS

::Before and ::after Pseudo‑Elements in CSS. ::beforeand::afterPseudo‑Elements in CSS
Understanding the :hover Pseudo‑Class in CSS. Understanding the
:hoverPseudo‑Class in CSS
Using the CSS :has Pseudo‑Class. Using the CSS
:hasPseudo‑Class
Optimising Angular Forms: Template‑Driven vs. Reactive Forms. Optimising Angular Forms: Template‑Driven vs. Reactive Forms

Rendering Lists in React and Why Keys Matter. Rendering Lists in React and Why Keys Matter

How to Read JavaScript Errors and Stack Traces. How to Read JavaScript Errors and Stack Traces

Breadth‑First Search: Solving Binary Tree Level Order Traversal. Breadth‑First Search: Solving Binary Tree Level Order Traversal

Staying Current: Automating Copyright Year Updates. Staying Current: Automating Copyright Year Updates

Understanding CSS Positioning. Understanding CSS Positioning

Has Google Killed AMP? Has Google Killed AMP?

Caching Strategies in React. Caching Strategies in React