CSS content Property

Beginner
⏱️ 6 min read
📚 Updated: Jun 2026
🎯 4 Examples
Pseudo-Elements

What You’ll Learn

The content property inserts generated content into ::before and ::after pseudo-elements — no extra HTML required.

01

Generated Content

CSS-inserted text.

02

::before / ::after

Required context.

03

Default normal

No content shown.

04

Text & URLs

Strings and images.

05

attr()

From HTML attrs.

06

Decorative

Presentational use.

Definition and Usage

The content CSS property is used with the ::before and ::after pseudo-elements to insert generated content into an element. It is particularly useful for adding decorative content or presentational annotations without altering the HTML markup.

Common uses include labels like “Note:”, icons before list items, external-link arrows after anchors, quote marks, and counter numbers. Remember: essential information should stay in HTML for accessibility; use content for decoration and enhancement.

💡
Beginner Tip

A pseudo-element only appears when content is set to something other than normal or none. Empty string content: ""; creates an invisible box you can style as a shape or icon background.

📝 Syntax

The syntax for content is flexible — it can include text, images, counters, and attribute values:

syntax.css
selector::before {
  content: "text" | url(image) | counter(name) | attr(attribute) | open-quote | close-quote | normal | none;
}

Basic Example

content-note-before.css
p::before {
  content: "Note: ";
  font-weight: bold;
  color: red;
}

Syntax Rules

  • The initial value is normal — no generated content appears.
  • Only works on pseudo-elements like ::before, ::after, and ::marker.
  • Text strings must be wrapped in quotes: content: "Hello";.
  • Combine values: content: "Step " counter(step);.
  • Use content: none; to suppress default marker or quote content.

⚡ Quick Reference

QuestionAnswer
Initial valuenormal
Applies to::before, ::after, ::marker
InheritedNo
AnimatableNo
Common useLabels, icons, and decorative prefixes via pseudo-elements

💎 Property Values

The content property accepts strings, functions, and keyword values.

ValueDescription
textA string of text, e.g. content: "Note: ";
url(image)A URL to an image, e.g. content: url("icon.svg");
counter(name)A CSS counter value for numbered lists or steps.
attr(attribute)The value of an HTML attribute on the element.
open-quoteInserts an opening quote character.
close-quoteInserts a closing quote character.
no-open-quoteDoes not insert an opening quote.
no-close-quoteDoes not insert a closing quote.
normalDefault value; does not generate content.
noneNo content is generated.
"Note: " attr(data-label) url(icon.svg) counter(item) open-quote

👀 Live Preview

A paragraph with p::before { content: "Note: "; } — bold red text inserted before the message.

This is an important message.

Examples Gallery

Try a text prefix, attr() label, decorative icon, and external-link arrow with ::after.

📝 Text Content

Start with the reference example — add a bold red “Note:” prefix before a paragraph.

Example 1 — Text Before a Paragraph

Use content on ::before to add text before a paragraph.

content-note.html
<style>
  p::before {
    content: "Note: ";
    font-weight: bold;
    color: red;
  }
</style>

<p>This is an important message.</p>
Try It Yourself

How It Works

The browser creates a ::before pseudo-element and inserts the string before the paragraph’s text content.

Example 2 — attr() for Custom Labels

Pull a label from a data-label attribute into generated content.

content-attr.css
.tag::before {
  content: attr(data-label) ": ";
  font-weight: 600;
  color: #2563eb;
}
Try It Yourself

How It Works

attr(data-label) reads the attribute value from HTML, keeping labels in markup while styling them with CSS.

🎨 Decorative Content

Use Unicode characters and ::after content for icons and link indicators.

Example 3 — Icon Bullet with ::before

Add a star icon before each list item using a Unicode character in content.

content-icon.css
.custom-list li::before {
  content: "★ ";
  color: #f59e0b;
}
Try It Yourself

How It Works

Unicode symbols in content work like lightweight icons without image files. You can also use url() for SVG or PNG assets.

🧠 How content Works

1

Target a pseudo-element

Write a rule for ::before or ::after on a selector.

Prerequisite
2

You set content

Provide a string, url(), attr(), or keyword value.

CSS rule
3

Browser generates a box

The pseudo-element appears inline with the element, styled by your other CSS rules.

Rendering
=

Decorative enhancement

Extra visual content appears without changing your HTML structure.

Modern Browser Support

The content property is widely supported across all modern browsers, including Chrome, Firefox, Safari, Edge, and Opera.

Baseline · Modern browsers

Generated content everywhere

All major browsers support content on pseudo-elements, including older versions of these browsers.

99% Modern browser support
Google Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions
Full support
Opera All modern versions
Full support
content property 99% supported

Bottom line: Use content reliably on pseudo-elements. Keep critical text in HTML for accessibility.

Conclusion

The content property in CSS is a versatile tool for inserting generated content without altering the HTML structure. It can be particularly useful for adding decorative elements, annotations, or other presentational content.

By understanding and utilizing the content property, you can enhance the visual appeal and functionality of your web projects.

💡 Best Practices

✅ Do

  • Use content for decorative labels, icons, and indicators
  • Pair with ::before and ::after pseudo-elements
  • Use attr() for data-driven presentational hints
  • Keep essential information in HTML for screen readers
  • Use content: ""; to create styled shape boxes

❌ Don’t

  • Put critical content only in CSS generated text
  • Apply content directly to regular elements — it has no effect
  • Rely on generated content for SEO-important text
  • Forget quotes around text strings
  • Overuse decorative prefixes that clutter the UI

Key Takeaways

Knowledge Unlocked

Five things to remember about content

Use these points when inserting generated content.

5
Core concepts
02

Default normal

No content.

Default
🖌 03

::before/::after

Required context.

Syntax
📝 04

Many values

Text, url, attr.

Values
05

Decorative

Not essential text.

A11y

❓ Frequently Asked Questions

content inserts generated content into ::before and ::after pseudo-elements. It lets you add decorative or presentational text and icons without changing HTML markup.
The initial value is normal, which means no content is generated for the pseudo-element.
No. content only applies to ::before, ::after, and ::marker pseudo-elements (and similar generated-content contexts). Setting content on a div has no effect.
HTML text is part of the document and accessible to screen readers by default. Generated content from CSS is presentational — use it for decoration, not essential information.
Write content: attr(data-label) or content: attr(href) to pull a value from an HTML attribute into the pseudo-element, such as showing a link URL on hover.

Practice in the Live Editor

Open the HTML editor, add p::before { content: "Note: "; }, and preview generated content on a paragraph.

HTML Editor →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful