10 min read

CSS Pseudo-Elements: ::before, ::after, and Beyond

10 min read
311 words
18 sections15 code blocks

What Are Pseudo-Elements?

Pseudo-elements let you style specific parts of an element or insert content that doesn't exist in the HTML. They use the double colon (::) syntax and create virtual elements you can style like real ones.

CSS
/* Pseudo-element syntax */
selector::pseudo-element {
  /* styles */
}

::before and ::after

The most commonly used pseudo-elements. They insert content before or after an element's actual content:

CSS
.element::before {
  content: ''; /* Required! Even if empty */
}

.element::after {
  content: '';
}

Critical rule: The content property is required for ::before and ::after to appear. Even if you want an empty element, use content: ''.

Adding Text Content

CSS
.required-field::after {
  content: ' *';
  color: red;
}

.external-link::after {
  content: ' \2197'; /* Arrow symbol */
  font-size: 0.8em;
}

.price::before {
  content: '$';
}

blockquote::before {
  content: '\201C'; /* Opening curly quote */
  font-size: 3rem;
  color: #ddd;
}

Decorative Elements

::before and ::after are commonly used for visual decorations without adding extra HTML:

CSS
/* Decorative line under heading */
.heading::after {
  content: '';
  display: block;
  width: 60px;
  height: 3px;
  background: #3498db;
  margin-top: 0.5rem;
}

/* Colored accent bar */
.card::before {
  content: '';
  display: block;
  height: 4px;
  background: linear-gradient(to right, #3498db, #8e44ad);
}

Tooltip Arrow

CSS
.tooltip {
  position: relative;
  background: #333;
  color: white;
  padding: 0.5rem 1rem;
  border-radius: 4px;
}

.tooltip::after {
  content: '';
  position: absolute;
  bottom: -8px;
  left: 50%;
  transform: translateX(-50%);
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
  border-top: 8px solid #333;
}

Animated Underline

CSS
.link {
  position: relative;
  text-decoration: none;
}

.link::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0;
  height: 2px;
  background: #3498db;
  transition: width 0.3s ease;
}

.link:hover::after {
  width: 100%;
}

::first-line

Styles the first line of a block element's text. The first line is determined by the element's width, so it adapts responsively:

CSS
p::first-line {
  font-weight: bold;
  font-size: 1.1em;
  color: #2c3e50;
}

article::first-line {
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

Limited properties: Only certain properties work with ::first-line, including font properties, color, background, text-decoration, text-transform, letter-spacing, and word-spacing.

::first-letter

Styles the first letter of a block element — great for drop caps:

CSS
/* Drop cap effect */
.article-body p:first-of-type::first-letter {
  font-size: 3.5em;
  font-weight: bold;
  float: left;
  line-height: 1;
  margin-right: 0.1em;
  color: #2c3e50;
}

::placeholder

Styles the placeholder text in input and textarea elements:

CSS
input::placeholder {
  color: #aaa;
  font-style: italic;
  font-size: 0.9em;
}

textarea::placeholder {
  color: #bbb;
}

::selection

Styles the portion of text that the user highlights (selects):

CSS
::selection {
  background: #3498db;
  color: white;
}

/* Specific element selection color */
.brand-section::selection {
  background: #e74c3c;
  color: white;
}

::marker

Styles the marker (bullet or number) of list items:

CSS
li::marker {
  color: #3498db;
  font-weight: bold;
  font-size: 1.2em;
}

ol li::marker {
  color: #e74c3c;
}

Practical Pseudo-Element Patterns

Custom Checkbox

CSS
.checkbox-custom {
  display: none;
}

.checkbox-label {
  position: relative;
  padding-left: 2rem;
  cursor: pointer;
}

.checkbox-label::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  border: 2px solid #ddd;
  border-radius: 3px;
  transition: all 0.2s;
}

.checkbox-custom:checked + .checkbox-label::before {
  background: #3498db;
  border-color: #3498db;
}

.checkbox-custom:checked + .checkbox-label::after {
  content: '\2713';
  position: absolute;
  left: 3px;
  top: 50%;
  transform: translateY(-50%);
  color: white;
  font-size: 14px;
}

Overlay on Image

CSS
.image-container {
  position: relative;
  overflow: hidden;
}

.image-container::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(transparent, rgba(0,0,0,0.7));
  opacity: 0;
  transition: opacity 0.3s ease;
}

.image-container:hover::after {
  opacity: 1;
}

Clearfix (Legacy)

CSS
.clearfix::after {
  content: '';
  display: table;
  clear: both;
}

Section Divider

CSS
.section-title {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.section-title::before,
.section-title::after {
  content: '';
  flex: 1;
  height: 1px;
  background: #ddd;
}

Important Rules

  1. content is required for ::before and ::after
  2. ::before and ::after don't work on void elements (img, input, br, hr)
  3. Each element can only have one ::before and one ::after
  4. Pseudo-elements are inline by default — set display: block or display: inline-block as needed
  5. Use double colons (::) for pseudo-elements (single colon for pseudo-classes)

Summary

CSS pseudo-elements are powerful tools for adding visual content and styling without extra HTML. ::before and ::after create decorative elements, tooltips, overlays, and animations. ::first-line and ::first-letter add typographic flair. ::placeholder and ::selection customize form inputs and text selection. Always remember that the content property is required for ::before and ::after to work.