Question

How to Use CSS content with HTML Entities in CSS

csshtmlhtml-entitiescss-content

Question

How can you use the CSS content property to insert characters that are normally written as HTML entities?

For example, why does this CSS display the literal text   instead of inserting a non-breaking space?

.breadcrumbs a::before {
  content: ' ';
}

What is the correct way to insert a non-breaking space or similar special character with CSS content?

Short Answer

By the end of this page, you will understand that CSS content does not parse HTML entities like  . Instead, CSS inserts plain text strings or Unicode characters. You will learn how to add special characters correctly using direct characters or Unicode escape sequences such as "\00a0".

Concept

CSS and HTML are parsed differently.

HTML entities like  , &, and © are part of HTML syntax, not CSS syntax. That means the CSS content property does not interpret   as a non-breaking space. It sees it as an ordinary string of characters and prints it exactly as written.

For example:

content: ' ';

This means:

  • start a string
  • place the characters &, n, b, s, p, ;
  • end the string

So the browser displays   literally.

To insert special characters with CSS content, use one of these approaches:

  • type the actual character directly, if appropriate
  • use a Unicode escape sequence such as "\00a0" for a non-breaking space

This matters because pseudo-elements like ::before and ::after are commonly used for:

  • separators in breadcrumbs
  • decorative icons
  • quotation marks
  • arrows and bullets
  • labels like Required or New

If you do not understand how content handles characters, your UI may show the wrong text or spacing.

Mental Model

Think of HTML entities as a language that HTML understands, but CSS does not.

  • HTML sees   and translates it into a special space.
  • CSS sees   inside quotes and treats it like a normal word.

A simple analogy:

  • HTML entities are like commands written for one machine.
  • CSS content is a different machine with different commands.
  • If you send an HTML command to CSS, CSS does not translate it. It just prints it.

So when using content, think in terms of:

  • plain text strings
  • Unicode characters
  • Unicode escape codes

not HTML entities.

Take Quiz

Syntax and Examples

The basic syntax for content with pseudo-elements looks like this:

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

selector::after {
  content: "text";
}

Example 1: Insert a normal string

.note::before {
  content: "Note: ";
}

This adds the text Note: before the element.

Example 2: Insert a non-breaking space

.breadcrumbs a::before {
  content: "\00a0";
}

\00a0 is the Unicode code point for a non-breaking space.

Example 3: Insert a separator with spacing

.breadcrumbs a + a::before {
  content: " / ";
}

This adds / before every breadcrumb link except the first one.

Example 4: Insert a copyright symbol

.footer::before {
  content: "\00a9 ";
}

This displays the copyright symbol followed by a normal space.

Example 5: Direct character instead of escape

You can sometimes type the character directly:

.footer::before {
  content: "© ";
}

This is valid too, as long as your file encoding is handled correctly.

Important note

Pseudo-elements usually need ::before or ::after to display generated content:

.label::after {
  content: " *";
  color: red;
}

Step by Step Execution

Consider this CSS:

.breadcrumbs a + a::before {
  content: "\00a0>\00a0";
}

And this HTML:

<nav class="breadcrumbs">
  <a href="/">Home</a>
  <a href="/products">Products</a>
  <a href="/products/shoes">Shoes</a>
</nav>

What happens step by step

  1. The browser finds every a inside .breadcrumbs.
  2. The selector a + a matches every link that comes immediately after another link.
  3. That means:
    • Home is not matched
    • Products is matched
    • Shoes is matched
  4. For each matched element, ::before creates a pseudo-element before the link text.
  5. The content value "\00a0>\00a0" is interpreted as:
    • a non-breaking space
    • the > character
    • another non-breaking space
  6. The rendered output becomes visually similar to:
Home > Products > Shoes

Why non-breaking spaces help

A normal space can wrap at the end of a line. A non-breaking space helps keep the separator attached more tightly to nearby text, depending on the layout.

Real World Use Cases

Developers use CSS content for many small interface details.

Breadcrumb separators

.breadcrumbs a + a::before {
  content: " / ";
}

Useful for navigation trails.

Required form labels

.required label::after {
  content: " *";
  color: red;
}

Adds a visual required marker.

External link indicator

a.external::after {
  content: " ↗";
}

Shows that a link opens an external resource.

Quotes or decorative marks

blockquote::before {
  content: "\201C";
}

Adds an opening quotation mark.

Status badges

.new::before {
  content: "New: ";
  font-weight: bold;
}

Adds short labels without changing the HTML.

These uses are best for presentation, not critical content that users must always access.

Take Quiz

Real Codebase Usage

In real projects, developers usually use CSS content for small presentational additions rather than meaningful data.

Common patterns

Visual separators

.breadcrumbs li + li::before {
  content: " / ";
  color: #666;
}

This avoids adding separator markup into every breadcrumb item.

Icons with Unicode characters

.download-link::before {
  content: "\2193 ";
}

Good for lightweight decorative icons.

Guarding the first item

Instead of adding a separator before every item, developers often use selectors like:

.item + .item::before {
  content: ", ";
}

This is similar to a guard clause in programming: only apply the separator when there is a previous item.

Keeping content decorative

Teams usually avoid placing essential business information only in ::before or ::after, because generated content may not be as reliable for accessibility, translation, or copy/paste workflows.

Prefer HTML for meaningful text

If the content is important, such as error messages, prices, or labels needed by screen readers, developers typically put it in the HTML or generate it from templates or JavaScript instead.

Common Mistakes

1. Using HTML entities in CSS strings

Broken example:

.box::before {
  content: "&copy;";
}

This prints &copy; literally.

Correct:

.box::before {
  content: "\00a9";
}

or

.box::before {
  content: "©";
}

2. Forgetting to use a pseudo-element

Broken example:

.box {
  content: "Hello";
}

For normal elements, content does not work the way beginners often expect.

Correct:

.box::before {
  content: "Hello";
}

3. Using one colon in modern code without consistency

Older CSS used :before. Modern CSS prefers ::before and ::after.

.box::before {
  content: "*";
}

Most browsers support both, but ::before is clearer.

4. Forgetting quotes around strings

Broken example:

.box::before {
  content: Hello;
}

Correct:

.box::before {
  content: "Hello";
}

5. Assuming generated content is always accessible

Using CSS to add important warnings or instructions can be risky.

Avoid this for critical information:

.error::before {
  content: "Form submission failed: ";
}

Prefer real HTML content for important messages.

6. Using the wrong Unicode escape format

CSS Unicode escapes start with a backslash.

Correct:

content: "\00a0";

Not:

content: "00a0";

Comparisons

ApproachWorks in CSS content?ExampleNotes
HTML entityNo"&nbsp;"Printed literally in CSS
Direct characterYes"©"Easy to read if encoding is reliable
Unicode escapeYes"\00a9"Best when you want explicit, portable character insertion
Regular text stringYes"Hello"Most common use

::before vs ::after

Pseudo-elementPurposeExample
::beforeInsert content before the element's contentAdd icons before links
::afterInsert content after the element's contentAdd badges or arrows after text

CSS content vs real HTML text

OptionBest forAvoid for
CSS contentDecorative labels, separators, symbolsCritical text or structured content
HTML textMeaningful content, accessible labels, dataPurely decorative repetition
Take Quiz

Cheat Sheet

Quick rules

  • CSS content does not understand HTML entities like &nbsp;
  • Use ::before or ::after
  • Use quoted strings for text
  • Use Unicode escapes for special characters
  • Prefer HTML for important content

Common syntax

.element::before {
  content: "Hello";
}
.element::before {
  content: "\00a0";
}

Useful Unicode values

  • Non-breaking space: \00a0
  • Copyright: \00a9
  • Right arrow: \2192
  • Opening double quote: \201C
  • Closing double quote: \201D
  • Bullet: \2022

Example fixes

Wrong:

content: "&nbsp;";

Right:

content: "\00a0";

or

content: " ";

Good breadcrumb pattern

.breadcrumbs a + a::before {
  content: " / ";
}

FAQ

Why does &nbsp; print literally in CSS?

Because &nbsp; is an HTML entity, and CSS does not parse HTML entities inside content strings.

How do I insert a non-breaking space in CSS?

Use a Unicode escape:

content: "\00a0";

Can I type the actual special character directly in CSS?

Yes. For many characters, you can write them directly, such as © or a real non-breaking space, but Unicode escapes are often clearer.

Should I use :before or ::before?

Use ::before in modern CSS. :before is older syntax but still widely supported.

Is CSS-generated content good for accessibility?

It can be acceptable for decorative content, but important information should usually be in the HTML.

Can I add icons using CSS content?

Yes. You can use Unicode symbols or icon fonts, but simple Unicode characters are often the easiest option.

Does content work on normal elements without pseudo-elements?

Usually, beginners should think of content as something used with ::before and ::after. That is the common and practical use case.

Take Quiz

Mini Project

Description

Build a breadcrumb navigation style that inserts separators between links using CSS generated content. This demonstrates the correct way to add visual characters in CSS without using HTML entities like &nbsp;.

Goal

Create breadcrumb links that display a separator before each item except the first, using ::before and valid CSS content values.

Requirements

  • Create a breadcrumb navigation with at least three links.
  • Add separators using CSS ::before instead of putting separator text in the HTML.
  • Do not show a separator before the first breadcrumb item.
  • Use either plain text separators or Unicode escapes in the content property.
  • Keep the HTML clean and readable.
Take Quiz

Keep learning

Related questions

View more