Kombai Logo

Tailwind CSS Content

When working with CSS, the content property plays a crucial role in defining content for pseudo-elements like ::before and ::after. Tailwind CSS provides content utility that can be used with the before and after modifiers to style and control the display of pseudo-elements.

ClassPropertiesExample
content-nonecontent: none;<div className="content-none"></div>

Overview of Content

Adding the Pseudo-elements Content

To add content to ::before or ::after pseudo-element, use the before:content-['*'] or after:content-['*'] variants. The text inside brackets defines the content to be displayed.

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

Linking Attributes with Content

To allow pseudo-elements to reference an attribute value, use the content-[attr(attribute-name)] syntax to dynamically populate the pseudo-element:

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

Adding Spaces and Underscores

To add a space inside the content, use underscores(_), e.g, content-["Spaced_Content"]. When you have to actually add an underscore, escape it with a backslash, e.g., content-["Underscored\_Content"].

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

States and Responsiveness

Hover and Focus States

Tailwind CSS allows you to conditionally apply content styles. By prepending state modifiers like hover: or focus:, you can change pseudo-element content based on user interaction:

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

Breakpoint Modifiers

Tailwind’s breakpoint modifiers allow you to modify the content of pseudo-elements based on screen size. This approach provides responsive designs by appending breakpoint prefixes such as sm:, md:, or lg:.

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

Custom Content

Extending the Theme

Tailwind, by-default, only provides the content-none utility. However, it lets you define custom content values.

To add a new content utility, extend the content property in the theme section of your tailwind.config.js. Once added, use the custom values via their class names:

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

Using Arbitrary Values

Arbitrary values allow you to use one-off values without extending the theme. To use an arbitrary content value, surround the desired value with square brackets [] in the utility class.

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

Real World Examples

Product Card with Sale Badge

A product card component that displays a "SALE" badge in the top-right corner using content-['SALE'] before pseudo-element.

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

Required Form Fields Indicator

A form component that shows required fields with an asterisk using content-['*'] before pseudo-element.

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

Feature List with Checkmarks

A feature list component that adds checkmark icons using content-['✓'] before pseudo-element.

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

A social media links component that adds icons using content-['→'] before pseudo-element with hover effects.

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

A breadcrumb component that adds custom arrow separator using content-['→'] after pseudo-element.

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

Customization Examples

Animated Progress Steps

An animated progress indicator with custom step markers and transitions.

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

Social Card with Icon Decorators

A social card with custom icon decorators using content utility.

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

File Card with Status Icons

A file card using content utility for status and action icons

This is a live editor. Play around with it!
export default function App() {
  return <h1>Hello world</h1>
}

Best Practices

Maintain Design Consistency

Using content-* utilities in Tailwind CSS effectively requires a structured approach to maintain design consistency. These utilities allow for inserting generated content before or after elements using before:content-[''] or after:content-[''].

Ensuring a uniform look across a project involves adhering to predefined design patterns and avoiding inconsistent use of content insertion. For example, when using the content utility to add icons, indicators, helper text, etc., it is best to follow a uniform typography, size, and color scheme to avoid discrepancies.

Optimize for Reusability

Reusability is critical when working with content-* utilities, especially in component-driven development. By default, Tailwind only provides content-none, so custom content utilities must be defined in the Tailwind configuration. Using the extend property within the theme section of tailwind.config.js, developers can add custom content utilities for frequent use.

For instance, defining custom utilities such as before:content-['✓'] or after:content-['→'] ensures that commonly used pseudo-elements are standardized across the project. This eliminates the need for inline styles, reducing redundancy and improving maintainability.

Accessibility Considerations

Enhance Readability and Navigability

Readability is a critical factor when using content-* utilities. Dynamically inserted content should always complement, rather than obscure, surrounding text. Using appropriate contrast, spacing, and font sizes ensures that the added content remains legible for all users.

For navigability, content insertion should not disrupt logical content flow. If before:content-[''] is applied to headings or paragraphs, ensuring appropriate margin spacing with before:mr-2 prevents visual distractions.

Keyboard navigation should also be factored in. Since pseudo-elements are not focusable by default, they should be used only for decorative purposes rather than essential interactive elements.

Support Accessible Interactive Elements

Interactive elements should not rely solely on content-* utilities for functionality. Since pseudo-elements (::before and ::after) are not part of the DOM in a way that allows user interaction, they cannot receive focus or click. This means that any critical functionality—such as navigation, form actions, or buttons—should not be dependent on content-* for essential behavior. Instead, pseudo-elements should be treated as visual enhancements to improve aesthetics without affecting usability.

For example, a breadcrumb navigation can use before:content-['→'] to add a separator, but the actual clickable links should still be standard <a> elements for proper focusability and accessibility. Similarly, a list styled with after:content-['✓'] should still contain real text.