CSS ::before Pseudo-Element

The ::before pseudo-element creates a generated element as the first child of a selected element. It is commonly used to insert decorative text, symbols, icons, and other visual content before existing content without adding extra HTML elements. The generated content is typically defined using the CSS content property.

Syntax

selector::before {
  content: "Generated content";
}

The selector identifies the element that receives the generated content.

The ::before pseudo-element creates a generated element as the first child of the selected element.

The content property specifies what the pseudo-element displays.

For example:

p::before {
  content: "Note: ";
}

This rule adds the text "Note: " before the existing content of each selected paragraph.

The generated text is displayed by CSS and does not become part of the original HTML markup.

How It Works

The ::before pseudo-element creates generated content that behaves as the first child of the selected element.

Although its name suggests that it appears before the element, the pseudo-element is generated inside the element, before its existing child content.

Consider the following HTML:

<p class="notice">Important information</p>

The following CSS adds a symbol before the paragraph text:

.notice::before {
  content: "\2605  ";
  color: #cc6600;
}

The displayed result is:

Browser Result

Important information

The star is generated by CSS. It is not present in the original HTML.

The pseudo-element can be styled using properties such as color, background, font-size, margin, and display.

Note: In ordinary usage, the pseudo-element requires a content declaration with a value other than none or normal to generate a box.

The content Property

The CSS content property determines what the ::before pseudo-element generates.

Common values include:

  • content: "text"; - Inserts a text string.
  • content: ""; - Creates an empty pseudo-element that can be styled.
  • content: "\2192"; - Inserts a character using a CSS Unicode escape.
  • content: attr(title); - Inserts the value of an HTML attribute.
  • content: url("icon.svg"); - Inserts an image as generated content.
  • content: none; - Prevents the pseudo-element from being generated.

For example, the following rule adds an arrow before elements with a particular class:

.arrow-label::before {
  content: "\2192  ";
  color: #0066cc;
}

The \2192 escape represents a right arrow character.

When using content: "", the pseudo-element can still display a background, border, or other decorative styling.

The generated content can also be positioned independently using CSS layout and positioning properties.

Adding Text and Symbols

The ::before pseudo-element is frequently used to add short decorative text or symbols before existing content.

Adding an Arrow

.navigation-link::before {
  content: "\2192";
  margin-right: 8px;
  color: #0066cc;
}

This rule adds a right arrow before elements with the navigation-link class.

Adding a Decorative Star

.featured-item::before {
  content: "\2605";
  margin-right: 6px;
  color: #cc6600;
}

The \2605 escape represents a filled star character.

This example adds a decorative star before featured items.

Adding Quotation Marks

.quote::before {
  content: open-quote;
}
.quote::after {
  content: close-quote;
}

This example combines ::before and ::after to display quotation marks around an element's content.

The quotation marks are generated by CSS rather than written directly in the HTML.

Styling Generated Content

Generated content can be styled with many of the same CSS properties used on ordinary HTML elements.

.highlight-label::before {
  content: "TIP";
  display: inline-block;
  margin-right: 8px;
  padding: 3px 8px;
  background: #0066cc;
  color: #fff;
  font-size: 12px;
  font-weight: bold;
  border-radius: 4px;
}

The display: inline-block declaration allows the generated content to have padding and dimensions while remaining on the same line as the existing content.

The margin-right property adds spacing between the generated label and the original text.

The background, text color, font size, and border radius create a small visual badge.

Because generated content may not be consistently announced by assistive technology, essential labels such as "TIP" should also be represented in the HTML when they communicate important information.

Example

The following example creates a list of CSS topics with decorative arrows generated before each link.

HTML:

<ul class="css-topic-list">
  <li><a href="/css3/references/css-selector-list.html">CSS Selectors</a></li>
  <li><a href="/css3/references/css-pseudo-class-list.html">CSS Pseudo-Classes</a></li>
  <li><a href="/css3/references/css-pseudo-element-list.html">CSS Pseudo-Elements</a></li>
</ul>

CSS:

.css-topic-list {
  list-style: none;
  padding: 0;
}
.css-topic-list li {
  margin-bottom: 10px;
}
.css-topic-list a {
  display: inline-block;
  color: #0066cc;
  text-decoration: none;
}
.css-topic-list a::before {
  content: "\2192";
  display: inline-block;
  margin-right: 8px;
  transition: transform 0.2s ease;
}
.css-topic-list a:hover::before {
  transform: translateX(4px);
}
.css-topic-list a:focus-visible {
  outline: 2px solid #0066cc;
  outline-offset: 3px;
}

The displayed result is:

Browser Result

The list displays a right arrow before each CSS topic link.

When the pointer moves over a link, its arrow shifts four pixels to the right.

The transition property creates smooth movement between the normal and hover states.

The :focus-visible rule provides a visible focus indicator for keyboard navigation.

The arrows are decorative. Each link remains understandable without the generated symbol.

Creating Decorative Elements

The ::before pseudo-element can create decorative shapes, lines, and background effects without requiring additional HTML elements.

An empty content value is commonly used when the pseudo-element does not need to display text.

Creating a Colored Line

.section-heading::before {
  content: "";
  display: inline-block;
  width: 4px;
  height: 20px;
  margin-right: 10px;
  background: #0066cc;
  vertical-align: middle;
}

This rule creates a narrow blue line before the heading text.

The vertical-align property helps align the decorative line with the text.

Creating a Decorative Circle

.custom-item::before {
  content: "";
  display: inline-block;
  width: 10px;
  height: 10px;
  margin-right: 8px;
  background: #0066cc;
  border-radius: 50%;
}

The border-radius: 50% declaration creates a circular decoration.

Creating a Corner Decoration

.decorated-box {
  position: relative;
  padding: 20px;
  border: 1px solid #ccc;
}
.decorated-box::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 20px;
  height: 20px;
  background: #0066cc;
}

The position: relative declaration establishes the containing block for the absolutely positioned pseudo-element.

The top and left properties position the decorative square in the upper-left corner of the box.

Because the decoration is generated with CSS, no additional HTML element is required.

Using HTML Attributes

The attr() function can retrieve an attribute value from the selected HTML element and display it as generated content.

For example, an element can contain a custom data-prefix attribute.

HTML:

<span class="code-label" data-prefix="CSS">Selectors</span>

CSS:

.code-label::before {
  content: attr(data-prefix) ": ";
  color: #0066cc;
  font-weight: bold;
}

The displayed result is:

Browser Result

Selectors

If the data-prefix attribute changes, the generated content reflects the updated value.

The attr() function is useful for decorative labels and supplemental information, but essential information should remain available in the HTML content.

::before vs. ::after

The ::before and ::after pseudo-elements both create generated content associated with a selected element.

The primary difference is where the generated content is inserted.

  • ::before - Creates a generated element as the first child of the selected element.
  • ::after - Creates a generated element as the last child of the selected element.

For example:

.example::before {
  content: "[";
}
.example::after {
  content: "]";
}

With the following HTML:

<span class="example">CSS</span>

The displayed result is:

Browser Result

CSS

The opening bracket is generated before the existing content, and the closing bracket is generated after it.

Both pseudo-elements can be styled independently using CSS.

They are frequently used together to create decorative borders, quotation marks, and other visual effects.

Limitations

Although ::before is widely supported, there are several important limitations.

  • Generated content does not become part of the original HTML markup.
  • The pseudo-element generally requires a content declaration to generate a visible box.
  • It cannot be used reliably on replaced elements such as <img> or <input>.
  • Generated content is not a substitute for meaningful HTML content.
  • Accessibility support for generated text can vary between assistive technologies.
  • The pseudo-element does not create an independent HTML element that can receive its own attributes or event listeners.

For example, the following selector should not be relied upon to add visible content inside an image element:

img::before {
  content: "Image label";
}

The HTML <img> element is a replaced element, and ::before does not provide a reliable way to prepend generated content to it.

Use appropriate HTML elements when content needs its own structure, semantics, or interaction behavior.

Accessibility Considerations

The ::before pseudo-element is best suited for decorative content and visual enhancements.

  • Do not use generated content as the only source of essential information.
  • Keep meaningful text, instructions, and labels in the HTML document.
  • Do not rely on CSS-generated symbols alone to communicate errors or required fields.
  • Ensure that decorative content does not interfere with reading order or visual clarity.
  • Use semantic HTML elements for interactive controls instead of attempting to create them with pseudo-elements.
  • Test generated content with assistive technologies when its presentation could affect understanding.

For purely decorative generated text, the content property supports an alternative text form using a slash and an empty string.

.decorative-link::before {
  content: "\2192 " / "";
}

The empty alternative text indicates that the arrow does not need to contribute spoken content in implementations supporting this syntax.

Because accessibility behavior can vary, essential information should still be provided directly in the HTML.

When a generated symbol communicates meaning, such as a warning or required field indicator, provide the same meaning through accessible HTML content or attributes.

Browser Support

The ::before pseudo-element is widely available across modern browsers, including Chrome, Edge, Firefox, Safari, and Opera.

The modern syntax uses two colons, ::before, to identify it as a pseudo-element.

For compatibility with older CSS implementations, browsers also support the legacy single-colon syntax :before.

The double-colon syntax is recommended for new stylesheets because it distinguishes pseudo-elements from pseudo-classes.

Support for individual features used with ::before, such as newer content values or animations, may vary independently.

For current compatibility information, visit Can I Use? .

Specifications

The ::before pseudo-element is defined in the CSS Pseudo-Elements Module Level 4 .

The content property and generated content behavior are also described in the CSS Generated Content Module Level 3 .