Pseudo-elements
A pseudo-element is a part of an element that has no separate tag in the markup: the first letter of a paragraph, a list marker, the hint text in a field. CSS lets you style such a part and even create a new one. Pseudo-elements are written after a selector with a double colon ::.
before and after
::before and ::after add content at the start and at the end of an element. What to add is set by the content property:
<style>
.price::before {
content: "$";
}
</style>
<p class="price">25</p>The markup has only the number, and CSS added the dollar sign. Such text cannot be selected with the mouse and copied, so content holds only decoration, not important information.
Icons and marks
content is handy for adding repeated icons — for example, an arrow on links that lead to another site:
<style>
a[target="_blank"]::after {
content: " ↗";
}
.required::after {
content: " *";
color: crimson;
}
</style>
<p><a href="#" target="_blank">An external link</a></p>
<p class="required">A required field</p>The icon appears on every matching element by itself — no need to type it into the markup by hand.
Decorative shapes
If content is empty (content: ""), the pseudo-element can become a shape: give it a size, a background and rounding. For the sizes to work, it gets display: inline-block or block:
<style>
.status::before {
content: "";
display: inline-block;
width: 10px;
height: 10px;
margin-right: 6px;
border-radius: 50%;
background: limegreen;
}
</style>
<p class="status">Online</p>First letter and first line
::first-letter styles the first letter, and ::first-line styles the first line of text. This is how a drop cap is made, as in books:
<style>
.story::first-letter {
font-size: 2.5em;
font-weight: 700;
color: firebrick;
}
</style>
<p class="story">Once upon a time, in a small town, there lived a programmer who loved beautiful layouts.</p>Markers, placeholders and selection
::marker styles a list item's marker, ::placeholder styles the hint in an empty field, and ::selection styles text selected with the mouse:
<style>
li::marker { color: tomato; }
input::placeholder { color: teal; font-style: italic; }
p::selection { background: gold; }
</style>
<ul><li>A list item</li></ul>
<input placeholder="A hint in the field">
<p>Select this text with the mouse.</p>| Pseudo-element | What it styles |
|---|---|
::before, ::after | new content at the start and end |
::first-letter | the first letter |
::first-line | the first line |
::marker | a list item's marker or number |
::placeholder | the hint in a field |
::selection | selected text |
Common mistake
Without the content property, ::before and ::after do not appear at all, even with a size and a background:
<style>
.a::before, .b::before {
display: inline-block;
width: 12px;
height: 12px;
margin-right: 6px;
background: crimson;
}
.b::before { content: ""; }
</style>
<p class="a">No content — no square</p>
<p class="b">With content: "" — a square</p>Even an empty shape needs content: "".