CSS Pseudo-elements (::before, ::after, ::marker, ::selection, ::backdrop)
CSS pseudo-elements let you style parts of an element that do not exist as separate nodes in the HTML. They are useful for generated content, list markers, text selection styling, and certain modal or dialog backdrops.
Quick answer: Pseudo-elements target a part of an element, not the whole element itself. Use them when you want to add decorative or structural styling such as generated icons, custom list bullets, highlighted selections, or dialog backdrops.
Difficulty: Beginner
You'll understand this better if you know: basic CSS selectors, how the box model works, and the difference between HTML content and CSS styling.
1. What Are CSS Pseudo-elements?
CSS pseudo-elements are selector keywords that let you style a specific part of an element or insert content around it. They are written with a double colon, such as ::before, ::after, ::marker, ::selection, and ::backdrop.
- ::before and ::after create generated content before or after an element's content.
- ::marker styles list item markers like bullets and numbers.
- ::selection styles text the user highlights with the mouse or keyboard.
- ::backdrop styles the background layer behind elements such as modal dialogs and fullscreen content.
Pseudo-elements are different from pseudo-classes. A pseudo-class selects an element in a particular state, while a pseudo-element selects part of an element or generated content.
2. Why CSS Pseudo-elements Matter
Pseudo-elements help you add visual details without changing your HTML structure. That keeps markup cleaner and can make styles easier to maintain.
They are especially useful when you need:
- Decorative icons or labels that should not be in the document content.
- Custom bullets and numbering for lists.
- Selection styling that matches a design system.
- Backdrop styling for dialogs and fullscreen views.
They also support better separation of concerns. If the content is truly meaningful, it belongs in HTML. If it is only visual, a pseudo-element is often the better choice.
3. Basic Syntax or Core Idea
Pseudo-elements are attached to a selector, just like other selector parts. The most common syntax uses the double-colon form.
Basic selector pattern
Here is the general pattern for pseudo-elements:
selector::pseudo-element {
property: value;
}The selector matches the element, and the pseudo-element styles the part you want to affect. Some pseudo-elements, such as ::before and ::after, usually need the content property to appear.
Minimal example
This example adds decorative text before a heading:
h2::before {
content: "★ ";
color: #c28a00;
}In this case, the star is generated by CSS, not written into the HTML.
4. Step-by-Step Examples
Example 1: Adding decorative content with ::before
::before is often used for labels, icons, or visual emphasis. The content appears before the element's actual text.
.note::before {
content: "Note: ";
font-weight: bold;
}This is useful when the label is purely visual and does not need to be part of the HTML content.
Example 2: Appending a symbol with ::after
::after places generated content after the element's text. It is common for external-link indicators, required markers, or small decorative separators.
a::after {
content: " ↗";
}The arrow is added visually after every link without changing the HTML.
Example 3: Styling list markers with ::marker
::marker targets the marker box of list items. This is the modern way to style bullets and numbers directly.
li::marker {
color: #0a66c2;
font-weight: bold;
}This affects the bullet or number itself, not the whole list item.
Example 4: Styling text selection with ::selection
::selection applies when the user highlights text. It can improve readability and brand consistency when used carefully.
::selection {
background: #1e90ff;
color: #ffffff;
}This styles the highlighted text across the page, not just one element.
Example 5: Styling dialog backdrops with ::backdrop
::backdrop is used with elements that create a top layer, especially dialog and fullscreen content. It styles the dimmed area behind the active element.
dialog::backdrop {
background: rgba(0, 0, 0, 0.6);
}This helps focus attention on the dialog by visually separating it from the page behind it.
5. Practical Use Cases
- Add decorative quotation marks around testimonials without inserting extra HTML elements.
- Create consistent icon-like markers before menu items or alert labels.
- Customize bullets in ordered or unordered lists for documentation or product pages.
- Improve text-selection contrast in reading-heavy interfaces.
- Dim the page behind modal dialogs or fullscreen elements.
These use cases are strongest when the generated or target styling is presentational rather than content-critical.
6. Common Mistakes
Mistake 1: Forgetting the content property on ::before and ::after
::before and ::after do not render visible generated content unless content is set. Beginners often write styling but see nothing on the page.
Problem: The pseudo-element exists in the selector, but nothing appears because there is no generated content to render.
.badge::before {
color: #fff;
background: #d00;
}Fix: Add a content value so the pseudo-element has something to display.
.badge::before {
content: "New";
color: #fff;
background: #d00;
}The corrected version works because the browser has generated content to paint.
Mistake 2: Using ::marker on the wrong element
::marker only applies to list-item markers. If you attach it to arbitrary elements, the style will not affect bullets or numbers.
Problem: The selector targets a paragraph, but paragraphs do not have list markers, so the rule has no visible effect.
p::marker {
color: #0a66c2;
}Fix: Use ::marker on list items or list-item-like elements.
li::marker {
color: #0a66c2;
}The corrected selector works because the target element actually generates a marker box.
Mistake 3: Expecting ::selection to style every detail of selected content
::selection can change the text and background of selected text, but it does not let you fully redesign the selection UI or style every property.
Problem: Trying to use unsupported properties creates confusion when the selection looks unchanged or partly styled only.
::selection {
background: #222;
padding: 12px;
border: 2px solid #fff;
}Fix: Limit ::selection to properties it supports well, such as background and color.
::selection {
background: #222;
color: #fff;
}The corrected version works because it uses properties that browsers apply to highlighted text.
7. Best Practices
Practice 1: Use pseudo-elements for decorative content only
If the content matters to meaning, accessibility, or copying, put it in HTML instead of CSS. Use pseudo-elements for decorative labels, separators, and icons.
.card::before {
content: "";
display: block;
height: 4px;
background: #0a66c2;
}This keeps decorative styling in CSS while preserving meaningful HTML content.
Practice 2: Prefer ::marker for list markers instead of removing bullets
Instead of stripping list semantics and rebuilding them with extra elements, style the marker directly when possible. That keeps lists accessible and simpler.
ul {
padding-left: 1.5rem;
}
li::marker {
color: #0a66c2;
}This approach preserves the list structure while still giving you control over the marker appearance.
Practice 3: Keep ::selection readable and subtle
Selection styling should improve contrast, not fight the browser or overwhelm the page. Use clear foreground and background colors with sufficient contrast.
::selection {
background: #004aad;
color: #ffffff;
}A restrained selection style is easier to read and less distracting.
8. Limitations and Edge Cases
- ::before and ::after do not work on replaced elements such as many form controls and images.
- ::marker only applies where a marker box exists, typically on list items.
- ::selection does not support every CSS property, so some visual changes are ignored.
- ::backdrop only appears for elements that create a backdrop layer, such as open dialogs or fullscreen elements.
- Pseudo-elements are visual only; generated text may not be read the same way by assistive technology or included when content is copied.
Browser support is generally good for the modern double-colon syntax, but some older code bases still use single-colon forms for legacy compatibility. The double-colon notation is preferred for clarity.
9. Practical Mini Project
Let's build a small announcement card that uses several pseudo-elements together. The card will have a decorative top bar, a small label, and a custom highlight color for selected text.
::selection {
background: #1f6feb;
color: #ffffff;
}
.announcement {
position: relative;
padding: 1rem;
border: 1px solid #cfd7e6;
border-radius: 0.5rem;
background: #ffffff;
}
.announcement::before {
content: "Announcement";
display: inline-block;
margin-bottom: 0.5rem;
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
font-weight: bold;
color: #0b2e59;
background: #dbeafe;
border-radius: 999px;
}
.announcement::after {
content: "";
display: block;
height: 4px;
margin-top: 0.75rem;
background: linear-gradient(90deg, #1f6feb, #58a6ff);
}
.announcement ul {
padding-left: 1.25rem;
}
.announcement li::marker {
color: #1f6feb;
}This example combines generated labels, decorative structure, and custom list markers in a way that keeps the HTML simple.
10. Key Points
- Pseudo-elements style parts of an element or generate content around it.
- ::before and ::after usually need content to display.
- ::marker is for list markers, not general text.
- ::selection is for selected text and supports only a limited set of properties.
- ::backdrop styles the layer behind top-layer elements like dialogs.
11. Practice Exercise
- Style a product card so it has a small "Featured" label before the title using ::before.
- Make the list bullets inside the card blue using ::marker.
- Set a page-wide text selection color with ::selection.
Expected output: A card with a generated label above the title, blue list markers, and a custom selection highlight when text is selected.
Hint: Remember that ::before needs content, and ::marker only affects list items.
::selection {
background: #2b6cb0;
color: #ffffff;
}
.product-card {
padding: 1rem;
border: 1px solid #d7dde8;
border-radius: 0.5rem;
}
.product-card::before {
content: "Featured";
display: inline-block;
margin-bottom: 0.5rem;
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
font-weight: bold;
color: #1f2937;
background: #e0f2fe;
}
.product-card ul {
padding-left: 1.25rem;
}
.product-card li::marker {
color: #2b6cb0;
}The solution uses three pseudo-element families together while keeping the markup clean and semantic.
12. Final Summary
CSS pseudo-elements let you style specific parts of an element or generate decorative content without adding extra HTML. The most common ones are ::before, ::after, ::marker, ::selection, and ::backdrop.
Use them when the effect is visual, not content-critical. That usually means labels, icons, list markers, text selection colors, and backdrops for dialogs or fullscreen content. Keep in mind that some pseudo-elements need special conditions, such as content for generated content or an active top-layer element for ::backdrop.
As you practice, focus on choosing the right pseudo-element for the job and preserving semantic HTML. A good next step is to learn how pseudo-classes like :hover and :focus work alongside pseudo-elements in real layouts.