Pseudo-elements

Difficulty: Intermediate

Pseudo-elements let you style specific parts of an element or insert decorative content without adding extra HTML elements. They are written with a double colon prefix (::before, ::after) to distinguish them from pseudo-classes (single colon). Pseudo-elements create a 'virtual' element that you can style independently, keeping your HTML clean while enabling rich visual designs.

The ::before and ::after pseudo-elements insert content before or after an element's actual content. They require the content property to work - even if you want an empty pseudo-element for purely decorative purposes, you must include content: "". These pseudo-elements are inline by default but can be changed to block, flex, or any display type. They are children of the element they belong to, meaning position: absolute on ::before will position relative to the parent element (if the parent has position: relative).

::before and ::after are primarily used for decorative purposes: adding icons, creating geometric shapes, building custom underlines, overlay effects, clearfix patterns, and visual indicators like required field markers (label::after { content: "*"; color: red; }). They should not be used for meaningful content because screen readers may or may not read the content property, making it unreliable for accessibility. Keep important text in the HTML.

The ::first-line pseudo-element styles only the first line of a block-level element. The unique aspect is that it responds to the actual rendered first line, which changes with viewport width - as the browser window narrows, the first line gets shorter, and the styling adjusts accordingly. The ::first-letter pseudo-element targets only the first letter, enabling typographic effects like drop caps (large initial letters) commonly seen in newspapers and magazines.

The ::placeholder pseudo-element styles the placeholder text inside form inputs and textareas. This is useful for adjusting the color, font-size, or opacity of placeholder text to distinguish it from actual user input. The ::selection pseudo-element styles text that the user has highlighted/selected. You can change the background color and text color of selected text to match your site's branding. Note that only a limited set of properties work with ::selection: color, background-color, text-shadow, and cursor.

Code examples

::before and ::after Basics

/* Required field indicator */
label.required::after {
  content: " *";
  color: #ef4444;
  font-weight: bold;
}

/* Quotation marks */
.quote::before {
  content: "\201C"; /* Left double quotation mark */
  font-size: 3rem;
  color: #d1d5db;
  line-height: 0;
  vertical-align: -0.4em;
  margin-right: 4px;
}

/* Decorative line after heading */
.section-title::after {
  content: "";
  display: block;
  width: 60px;
  height: 3px;
  background-color: #3b82f6;
  margin-top: 8px;
  border-radius: 2px;
}

/* External link indicator */
a[href^="https"]::after {
  content: " \2197"; /* North-east arrow */
  font-size: 0.8em;
}

::before and ::after REQUIRE the content property. Use them for decorative elements (icons, lines, indicators) not for meaningful content. An empty content: '' creates an invisible element you can style as a shape or line.

Decorative Shapes with Pseudo-elements

/* Tooltip arrow using ::after */
.tooltip {
  position: relative;
  background: #1e293b;
  color: white;
  padding: 8px 16px;
  border-radius: 6px;
  display: inline-block;
}

.tooltip::after {
  content: "";
  position: absolute;
  bottom: -6px;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 6px solid #1e293b;
}

/* Card with colored top border using ::before */
.feature-card {
  position: relative;
  background: white;
  padding: 24px;
  border-radius: 8px;
  overflow: hidden;
}

.feature-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background-color: #3b82f6;
}

Pseudo-elements can create shapes like arrows (using borders), lines, and overlays without extra HTML. Position them absolutely relative to the parent element.

Text Pseudo-elements

/* Drop cap: large first letter */
.article-body::first-letter {
  font-size: 3.5rem;
  font-weight: bold;
  float: left;
  line-height: 1;
  margin-right: 8px;
  margin-top: 4px;
  color: #1e40af;
}

/* First line styling */
.article-body::first-line {
  font-weight: 600;
  color: #111827;
}

/* Custom placeholder styling */
input::placeholder {
  color: #9ca3af;
  font-style: italic;
  font-size: 14px;
}

/* Custom text selection */
::selection {
  background-color: #3b82f6;
  color: white;
}

/* Selection on specific elements */
.brand-text::selection {
  background-color: #f59e0b;
  color: #1e293b;
}

::first-letter enables drop cap effects. ::first-line styles adapt to viewport changes. ::placeholder customizes form input hints. ::selection changes the highlight color when users select text.

Key points

Concepts covered

::before, ::after, ::first-line, ::first-letter, ::placeholder, ::selection, Content Property, Decorative Elements