- CSS Pseudo Elements Ultimate Guide
- What Are Pseudo Elements?
- Before/After Pseudo Elements
- Why Use Before/After Pseudo Elements
- Other Pseudo Elements
- ::first-letter
- ::first-line
- ::selection
- Conclusion
- ::after
- Try it
- Syntax
- Examples
- Simple usage
- HTML
- CSS
- Result
- Decorative example
- HTML
- CSS
- Result
- Tooltips
- HTML
- CSS
- Result
- Accessibility concerns
- Specifications
- Browser compatibility
- See also
- Found a content problem with this page?
- MDN
- Support
- Our communities
- Developers
CSS Pseudo Elements Ultimate Guide
You can technically create any CSS design without the use of pseudo elements, but doing so is much harder and leaves you with messy code. Pseudo elements are amazing since they allow you to add/modify the HTML code of your site from CSS which means your HTML can stay clean and the CSS can add the extra content it needs. This may seem really confusing but it will all make sense once we talk about the first type of pseudo element.
If you prefer to learn visually, check out the video version of this article.
What Are Pseudo Elements?
I briefly mentioned that pseudo elements are ways for you to add/modify your HTML from CSS, but it is actually a bit more than that. There are really two styles of pseudo elements.
The first and by far most popular type are pseudo elements that allow you to add content to your HTML from CSS. There are only two of these pseudo elements (before and after) and we will be spending most of the time in this article on these pseudo elements.
The other style of pseudo elements allow you to treat specific sections of your HTML as if they were their own element. Good examples of this are the first-letter and first-line pseudo element that allow you to style the first letter or line of text as if it was its own element. Another example is the selection pseudo element that allows you to style the text that is highlighted. Try highlighting any text in this paragraph and you will see this selector in effect. Below is the CSS I used for this effect.
.class::selection background-color: red; color: white; >
You will notice that the selection pseudo element has two colons before it. This is how you define every single pseudo element. You put two colons at the start of the pseudo element and then put the pseudo element itself.
Before/After Pseudo Elements
In order to add content to your HTML you need to use the before and after pseudo elements. These pseudo elements allow you to add one child element as the first and/or last child element of whatever element you are selecting in your CSS.
.class-name::before /* This is the first child of .class-name */ > .class-name::after /* This is the last child of .class-name */ >
In the above code we are adding two new elements to the page. The before element is the first child and the after element is the last child. You will notice if this is all you do, though, nothing actually changes in your HTML. This is because the before/after pseudo elements require the content property to be set to a value in order to show up on the page. This content property defines what is put inside the new child element.
div class="class-name"> span>First Childspan> span>Second Childspan> div>
For the next example assume we start with the above HTML and then apply the below CSS.
.class-name::before content: "New First Child"; > .class-name::after content: ""; >
div class="class-name"> span>New First Childspan> span>First Childspan> span>Second Childspan> span>span> div>
You can now see that even though our original HTML only had 2 children our actual HTML that the browser sees has 4 children. Two of the children come from the HTML and the other 2 come from the CSS. If you inspect your page using the browser dev tools it will probably look something like the below example. I just wrote out what the actual HTML would look like in terms of how the browser actually renders the content.
div class="class-name"> ::before span>First Childspan> span>Second Childspan> ::after div>
You will also notice in our CSS that the content property for the after element is an empty string. This is very common to do and just means we don’t want to show any content in that element since we will instead do our own styling. This is useful when you want to create shapes with CSS like the triangle that shows up at the bottom of a tooltip.
Why Use Before/After Pseudo Elements
It may seem like these elements are useless, but they are really useful when you want to add specific content to specific HTML elements without repeating that content in your HTML.
For example, you can create the below button with a tooltip by using a single HTML element and having the CSS take care of all the tooltip code.
button data-tooltip="Hovered">Hover Mebutton>
[data-tooltip] position: relative; > [data-tooltip]::before content: attr(data-tooltip); position: absolute; left: 50%; bottom: calc(100% + 0.25rem); transform: translateX(-50%); background-color: blue; padding: 0.25rem 0.5rem; >
If you want to learn more about the attr function used in this example check out my data-attributes CSS article.
If I didn’t use pseudo elements in the above example then I would need to create a separate HTML element in my HTML that is just for the tooltip and that can get really messy and is prone to errors. This is why pseudo elements are much better.
Other Pseudo Elements
As I mentioned at the beginning of this article there are 2 styles of pseudo elements and while the before/after elements are the most common pseudo elements you will use there are still other useful elements you can use.
::first-letter
The first-letter pseudo element selects the first letter inside a p tag. You can actually see it in action at the start of this paragraph. This is great for adding special styling to your first letter like some books do for the first letter in a chapter. One thing to note is that only some CSS properties can be used when styling the first-letter. For example you cannot change things like the display or position properties, but you can change things like padding or color.
.class-name::first-letter font-size: 2em; color: red; font-weight: bold; >
::first-line
Similar to the first-letter pseudo element, the first-line pseudo element lets you change the style of just the first line of content in any block level element. This pseudo element is even more restricted on which CSS properties you can use. You cannot use things like margin or padding, but you can change pretty much anything to do with color or font.
.class-name::first-line color: red; >
::selection
We have already covered this pseudo element, but essentially it lets you style the highlighted content on a page. Again you can only use certain CSS properties. Pretty much only properties that modify the color or text-decoration are allowed. You can highlight this paragraph for an example.
.class::selection background-color: red; color: white; >
Conclusion
Pseudo elements are great for cleaning up your HTML while still having advanced CSS designs. The before and after pseudo elements will be the ones you use the most, but there are many other pseudo elements, even beyond the ones covered in this article, that will make doing specific things much easier.
::after
In CSS, ::after creates a pseudo-element that is the last 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 contained by the element’s formatting box, and thus don’t apply to replaced elements such as , or to elements.
Syntax
Note: CSS introduced the ::after notation (with two colons) to distinguish pseudo-classes from pseudo-elements. For backward compatibility, browsers also accept :after , introduced earlier.
Examples
Simple usage
Let’s create two classes: one for boring paragraphs and one for exciting ones. We can use these classes to add pseudo-elements to the end of paragraphs.
HTML
p class="boring-text">Here is some plain old boring text.p> p>Here is some normal text that is neither boring nor exciting.p> p class="exciting-text">Contributing to MDN is easy and fun.p>
CSS
.exciting-text::after content: " ; color: green; > .boring-text::after content: " ; color: red; >
Result
Decorative example
We can style text or images in the content property almost any way we want.
HTML
span class="ribbon">Look at the orange box after this text. span>
CSS
.ribbon background-color: #5bc8f7; > .ribbon::after content: "This is a fancy orange box."; background-color: #ffba10; border-color: black; border-style: dotted; >
Result
Tooltips
This example uses ::after , in conjunction with the attr() CSS expression and a data-descr custom data attribute, to create tooltips. No JavaScript is required!
We can also support keyboard users with this technique, by adding a tabindex of 0 to make each span keyboard focusable, and using a CSS :focus selector. This shows how flexible ::before and ::after can be, though for the most accessible experience a semantic disclosure widget created in some other way (such as with details and summary elements) is likely to be more appropriate.
HTML
p> Here we have some span tabindex="0" data-descr="collection of words and punctuation"> text span> with a few span tabindex="0" data-descr="small popups that appear when hovering"> tooltipsspan >. p>
CSS
span[data-descr] position: relative; text-decoration: underline; color: #00f; cursor: help; > span[data-descr]:hover::after, span[data-descr]:focus::after content: attr(data-descr); position: absolute; left: 0; top: 24px; min-width: 200px; border: 1px #aaaaaa solid; border-radius: 10px; background-color: #ffffcc; padding: 12px; color: #000000; font-size: 14px; z-index: 1; >
Result
Accessibility concerns
Using an ::after pseudo-element to add content is discouraged, as it is not reliably accessible to screen readers.
Specifications
Browser compatibility
BCD tables only load in the browser
See also
Found a content problem with this page?
This page was last modified on Feb 21, 2023 by MDN contributors.
Your blueprint for a better internet.
MDN
Support
Our communities
Developers
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998– 2023 by individual mozilla.org contributors. Content available under a Creative Commons license.