::before
In CSS, ::before creates a pseudo-element that is the first child of the selected element. It is often used to add cosmetic content to an element with the content property. It is inline by default.
Try it
Note: The pseudo-elements generated by ::before and ::after are boxes generated as if they were immediate children of the element on which they are applied, or the "originating element," and thus can not apply to replaced elements, such as <img>, whose content is outside the scope of the CSS formatting model.
Syntax
css
::before {
content: /* value */;
/* properties */
}
If the content property is not specified, has an invalid value, or has normal or none as a value, then the ::before pseudo-element is not rendered. It behaves as if display: none is set.
Note: Selectors Level 3 introduced the double-colon notation ::before to distinguish pseudo-classes from pseudo-elements. Browsers also accept single-colon notation:before, introduced in CSS2.
Examples
Adding quotation marks
One simple example of using ::before pseudo-elements is to provide quotation marks. Here we use both ::before and to insert quotation characters.::after
HTML
html
<q>Some quotes</q>, he said, <q>are better than none.</q>
CSS
css
q::before {
content: "«";
color: blue;
}
q::after {
content: "»";
color: red;
}
Result
Decorative example
We can style text or images in the content property almost any way we want.
HTML
html
<span class="ribbon">Notice where the orange box is.</span>
CSS
css
.ribbon {
background-color: #5bc8f7;
}
.ribbon::before {
content: "Look at this orange box.";
background-color: #ffba10;
border-color: black;
border-style: dotted;
}
Result
To-do list
In this example we will create a simple to-do list using pseudo-elements. This method can often be used to add small touches to the UI and improve user experience.
HTML
html
<ul>
<li>Buy milk</li>
<li>Take the dog for a walk</li>
<li>Exercise</li>
<li>Write code</li>
<li>Play music</li>
<li>Relax</li>
</ul>
CSS
css
li {
list-style-type: none;
position: relative;
margin: 2px;
padding: 0.5em 0.5em 0.5em 2em;
background: lightgrey;
font-family: sans-serif;
}
li.done {
background: #ccff99;
}
li.done::before {
content: "";
position: absolute;
border-color: #009933;
border-style: solid;
border-width: 0 0.3em 0.25em 0;
height: 1em;
top: 1.3em;
left: 0.6em;
margin-top: -1em;
transform: rotate(45deg);
width: 0.5em;
}
JavaScript
js
const list = document.querySelector("ul");
list.addEventListener(
"click",
(ev) => {
if (ev.target.tagName === "LI") {
ev.target.classList.toggle("done");
}
},
false,
);
Here is the above code example running live. Note that there are no icons used, and the check-mark is actually the ::before that has been styled in CSS. Go ahead and get some stuff done.
Result
Special characters
As this is CSS; not HTML, you can not use markup entities in content values. If you need to use a special character, and can not enter it literally into your CSS content string, use a unicode escape sequence, consisting of a backslash followed by the hexadecimal unicode value.
HTML
html
<ol>
<li>Crack Eggs into bowl</li>
<li>Add Milk</li>
<li>Add Flour</li>
<li aria-current="step">Mix thoroughly into a smooth batter</li>
<li>Pour a ladleful of batter onto a hot, greased, flat frying pan</li>
<li>Fry until the top of the pancake loses its gloss</li>
<li>Flip it over and fry for a couple more minutes</li>
<li>serve with your favorite topping</li>
</ol>
CSS
css
li {
padding: 0.5em;
}
li[aria-current="step"] {
font-weight: bold;
}
li[aria-current="step"]::after {
content: " \21E6"; /* Hexadecimal for Unicode Leftwards white arrow*/
display: inline;
}
Result
Accessibility concerns
Using a ::before pseudo-element to add content is discouraged, as it is not reliably accessible to screen readers.
Specifications
| Specification |
|---|
| CSS Pseudo-Elements Module Level 4 # generated-content |
Browser compatibility
BCD tables only load in the browser
