Pseudo-Elements
Overview
If pseudo-classes target the state of an element, pseudo-elements target a specific sub-part of an element, or allow you to literally inject fake HTML elements into the DOM purely using CSS. The ::before and ::after pseudo-elements are the secret weapon of advanced CSS design. They allow you to add decorative icons, tooltips, or complex shadows without polluting your actual HTML file with empty <div> tags.
Syntax
/* Notice the DOUBLE colon (::) for pseudo-elements */
/* 1. Targeting parts of text */
p::first-line { font-weight: bold; } /* Makes the first line of text bold */
p::first-letter { font-size: 3rem; float: left; } /* Drop-cap effect */
::selection { background: blue; color: white; } /* Styling the user's highlight */
/* 2. INJECTING Virtual Elements */
/* Adding a red asterisk after required form labels */
.label-required::after {
content: "*"; /* The content property is strictly required! */
color: red;
margin-left: 4px;
}
/* Creating an aesthetic quotation mark before a blockquote */
blockquote::before {
content: '"';
font-size: 4rem;
color: gray;
position: absolute;
}Common Pitfalls
- Forgetting the
contentproperty on::beforeor::after. If you don't declarecontent: "";(even an empty string), the browser refuses to render the pseudo-element entirely. It must have content to exist. - Trying to attach
::beforeto a replaced element like an<img>or<input>. Pseudo-elements are injected inside the element. Since an<img>cannot have children, pseudo-elements will silently fail on them.
Interview Questions
:) and a double colon (::) in CSS?In CSS2, everything used a single colon. CSS3 introduced the double colon strictly for pseudo-elements (::before) to mathematically separate them from pseudo-classes (:hover). However, browsers still support single colons for ::before for legacy compatibility.
Real-World Example
Using an empty ::after element to create a beautiful hover underline animation.
.nav-link {
position: relative;
text-decoration: none;
}
/* The virtual underline line (hidden by default) */
.nav-link::after {
content: "";
position: absolute;
bottom: -4px;
left: 0;
width: 0%; /* Starts invisible */
height: 2px;
background: blue;
transition: width 0.3s ease;
}
/* When the parent is hovered, expand the virtual line! */
.nav-link:hover::after {
width: 100%;
}Check Your Knowledge
Test your understanding of Pseudo-Elements with these quick questions.