Pseudo-elements allow you to style specific parts of an element or insert content before or after an element without adding extra HTML. They use a double colon (::) syntax and are incredibly powerful for creating decorative effects, icons, and enhanced typography—all with pure CSS.
What Are Pseudo-elements?
A pseudo-element is a keyword added to a selector that lets you style a specific part of the selected element. Unlike pseudo-classes (which target elements in a certain state), pseudo-elements target a portion of an element or allow you to insert new content.
/* Modern syntax: double colon (::) */
selector::pseudo-element {
property: value;
}
/* Examples */
p::first-letter {
font-size: 2em;
color: red;
}
.quote::before {
content: """;
font-size: 3em;
}
h1::after {
content: " ★";
}Single vs Double Colon: Older CSS (CSS2) used a single colon (:before, :after). CSS3 introduced double colons (::before, ::after) to distinguish pseudo-elements from pseudo-classes. Modern browsers support both, but double colons are recommended for clarity and future compatibility.
Pseudo-elements vs Pseudo-classes
| Aspect | Pseudo-elements (::) | Pseudo-classes (:) |
|---|---|---|
| Syntax | Double colon (::) | Single colon (:) |
| Purpose | Style specific parts or insert content | Target elements in specific states |
| Examples | ::before, ::after, ::first-letter | :hover, :focus, :nth-child() |
| Targets | Parts of elements or generated content | Whole elements based on state/position |
::before and ::after
The ::before and ::after pseudo-elements are the most powerful and commonly used. They insert content before or after an element's actual content, and you can style them just like regular elements.
Basic Syntax
/* Insert content before an element */
.element::before {
content: "Before text";
/* Additional styles */
}
/* Insert content after an element */
.element::after {
content: "After text";
/* Additional styles */
}
/* The content property is REQUIRED */
.element::before {
content: ""; /* Empty content, but still required */
display: block;
width: 50px;
height: 50px;
background-color: red;
}Critical: The content property is required for ::before and ::after to work, even if it's empty (content: ""). Without it, the pseudo-element won't appear.
Adding Text Content
The simplest use is adding text before or after elements:
::before and ::after with Text Content
Creating Decorative Elements
You can create shapes, icons, and decorative elements without adding extra HTML:
Decorative Elements with ::before and ::after
Creating Icons and Shapes
You can create CSS-only icons using ::before and ::after:
CSS-Only Icons with Pseudo-elements
Common Use Cases for ::before and ::after
- Quotation marks: Adding decorative quotes around text
- Icons: Simple icons without images
- Decorative shapes: Triangles, circles, lines
- Clearfix: Clearing floats (legacy technique)
- Tooltips: Creating tooltip arrows
- Counters: Automatic numbering
- Image overlays: Dark overlays on hover
::first-letter
The ::first-letter pseudo-element styles the first letter of the first line of a block-level element. It's perfect for creating drop caps and other typographic effects.
/* Style the first letter */
p::first-letter {
font-size: 3em;
font-weight: bold;
color: red;
float: left;
margin-right: 5px;
}
/* Drop cap effect */
article p:first-of-type::first-letter {
font-size: 4em;
line-height: 0.8;
float: left;
margin: 0.1em 0.1em 0 0;
font-family: Georgia, serif;
}::first-letter Pseudo-element Examples
Properties That Work with ::first-letter
Only certain CSS properties can be applied to ::first-letter:
- Font properties (font-size, font-weight, font-family, etc.)
- Color properties (color, background-color)
- Margin, padding, border
- Text decoration (text-decoration, text-transform)
- Float and clear
- Vertical-align (when float is none)
Note: ::first-letter only works on block-level elements (paragraphs, divs, headings, etc.), not inline elements like spans or links.
::first-line
The ::first-line pseudo-element styles the first line of text in a block-level element. The length of the first line depends on many factors, including the width of the element and font size.
/* Style the first line */
p::first-line {
font-weight: bold;
color: blue;
text-transform: uppercase;
}
/* Make first line stand out */
article p::first-line {
font-size: 1.2em;
letter-spacing: 1px;
}::first-line Pseudo-element Example
Properties That Work with ::first-line
Limited CSS properties can be applied to ::first-line:
- Font properties
- Color properties
- Background properties
- Word-spacing, letter-spacing, text-decoration
- Text-transform, line-height
- Clear, vertical-align
Dynamic Behavior: The ::first-line pseudo-element is dynamic—if you resize the browser window or change font size, the styling automatically updates to match whatever is now on the first line. This is different from ::first-letter, which always targets just the first character.
::selection
The ::selection pseudo-element styles the portion of an element that is selected by the user (highlighted with the mouse or keyboard).
/* Style selected text */
::selection {
background-color: yellow;
color: black;
}
/* Style selection for specific element */
p::selection {
background-color: #3498db;
color: white;
}
/* Firefox requires the -moz- prefix */
::-moz-selection {
background-color: yellow;
color: black;
}::selection Pseudo-element Example
Properties That Work with ::selection
Only a few properties are allowed with ::selection:
- color
- background-color (or background shorthand)
- cursor
- caret-color
- outline and its longhands
- text-decoration and its longhands
- text-emphasis-color
- text-shadow
💡 Browser Support:
Firefox requires the ::-moz-selection prefix for ::selection. For maximum compatibility, include both the standard and prefixed versions in your CSS.
::placeholder
The ::placeholder pseudo-element styles the placeholder text in input and textarea elements.
/* Style placeholder text */
input::placeholder {
color: #999;
font-style: italic;
opacity: 1; /* Firefox */
}
/* Different browsers need different prefixes */
input::-webkit-input-placeholder { /* Chrome/Safari/Edge */
color: #999;
}
input::-moz-placeholder { /* Firefox 19+ */
color: #999;
opacity: 1;
}
input:-ms-input-placeholder { /* IE 10-11 */
color: #999;
}
input::-ms-input-placeholder { /* Edge */
color: #999;
}::placeholder Pseudo-element Example
Combining Pseudo-elements
You can use multiple pseudo-elements on the same element (one ::before and one ::after), and you can combine pseudo-elements with pseudo-classes:
/* Both ::before and ::after on same element */
.box::before {
content: "Before";
}
.box::after {
content: "After";
}
/* Combine pseudo-element with pseudo-class */
button:hover::before {
content: "→ ";
}
/* Complex combination */
a:not(:hover)::after {
content: "";
display: block;
width: 0;
height: 2px;
background: blue;
transition: width 0.3s;
}
a:hover::after {
width: 100%;
}Combined Pseudo-elements Examples
Limitation: You can only have one ::before and one ::after per element. If you need more pseudo-elements, you'll need to add more HTML elements or use other techniques.
The content Property
The content property is crucial for ::before and ::after pseudo-elements. Here are the different values you can use:
content Property Values
| Property | Values | Description |
|---|---|---|
content: "text" | String | Insert text content |
content: "" | Empty string | Required even for decorative elements |
content: url(...) | Image URL | Insert an image |
content: attr(...) | HTML attribute | Display an element's attribute value |
content: counter(...) | Counter | Display automatic numbering |
content: open-quote | Opening quote | Insert opening quotation mark |
content: close-quote | Closing quote | Insert closing quotation mark |
Using attr() with content
The attr() function displays an element's attribute value:
attr() Function with content Property
Best Practices with Pseudo-elements
1. Always Include content Property
/* Won't work - missing content property */
.element::before {
display: block;
width: 50px;
height: 50px;
background: red;
}
/* Correct - content property included */
.element::before {
content: "";
display: block;
width: 50px;
height: 50px;
background: red;
}2. Use for Decorative Content Only
Accessibility: Content added with ::before and ::after is purely decorative and may not be read by screen readers. Never use pseudo-elements for meaningful content that users need to understand the page. Use real HTML for important content.
3. Keep Specificity in Mind
/* Pseudo-elements don't add to specificity much */
.element::before {
/* Same specificity as .element */
}
/* Can be overridden easily */
.element.active::before {
/* Higher specificity */
}4. Consider Performance
⚡ Performance Tip:
Using ::before and ::after is more performant than adding extra HTML elements because the browser doesn't need to parse additional DOM nodes. However, don't go overboard—if you need many decorative elements, consider using SVG or images instead.
Browser Support
All modern browsers support pseudo-elements with double-colon syntax. The single-colon syntax (:before, :after) still works for backward compatibility but use double colons (::before, ::after) for new projects. ::selection requires vendor prefixes for Firefox (::-moz-selection). ::placeholder needs vendor prefixes for full cross-browser support.
Key Takeaways
- Pseudo-elements style specific parts of elements or insert generated content
- Use double colon (::) syntax for modern pseudo-elements
- ::before and ::after insert content before or after elements
- The
contentproperty is required for ::before and ::after - ::first-letter styles the first letter of a block element
- ::first-line styles the first line of text
- ::selection styles selected/highlighted text
- ::placeholder styles form input placeholder text
- Pseudo-elements are purely decorative—don't use for essential content
- You can only have one ::before and one ::after per element
- Combine pseudo-elements with pseudo-classes for powerful effects
- Use
attr()to display HTML attribute values
What's Next?
Now that you've mastered both pseudo-classes and pseudo-elements, you're ready to learn about CSS Specificity and the Cascade. Understanding how CSS determines which styles to apply when multiple rules target the same element is crucial for writing maintainable CSS and troubleshooting styling issues.
Pseudo-elements are incredibly powerful for creating rich, visually appealing designs without cluttering your HTML. Practice using them to add decorative touches, create icons, and enhance typography—all while keeping your markup clean and semantic!