content (CSS property)

Inherited Initial Version
No normal CSS2, 2.1
Browser support (more…)
IE8+ FF3+ SA1.3+ OP9.2+ CH2+
Full Full Partial Partial Partial


content: { { string | uri | counter | attr(identifier) | open-quote | close-quote | no-open-quote | no-close-quote }  … | normal | none | inherit } ;


The content property, used in conjunction with the :before or :after pseudo-elements, inserts generated content.

Use the display property to control the type of box that’s generated for the content.

Note that the generated content is only rendered—it doesn’t appear in the DOM tree. In other words, generated content doesn’t alter the document as such—only the presentation.

That said, generated content is still matched by pseudo-elements like :first-letter and :first-line.

Here are some additional examples that demonstrate more advanced usage of generated content, including the use of the counter-increment and counter-reset properties.

This style rule adds the URI, enclosed in angle brackets, after links when the document’s printed to paper:

@media print {
  a[href]:after {
    content: "<" attr(href) ">";

These CSS3 style rules format paragraphs within a block quotation in the way that’s common in (American) English novels:

blockquote p {
  margin: 0;
  text-indent: 1em;
  quotes: "\201c" "\201d";
blockquote p:first-of-type {
  text-indent: 0;
blockquote p::before {
  content: open-quote;
blockquote p::after {
  content: no-close-quote;
blockquote p:last-of-type::after {
  content: close-quote;

These style rules add the word “Chapter” and a chapter number before every h1 heading, and prefix every h2 heading with the chapter number and a section number:

body {
  counter-reset: chapter;
h1 {
  counter-increment: chapter;
  counter-reset: section;
h2 {
  counter-increment: section;
h1:before {
  content: "Chapter " counter(chapter) ": ";
h2:before {
  content: counter(chapter) "." counter(section) " ";

These style rules apply a hierarchical numbering system to items in ordered lists (for example, 1, 1.1, 1.1.1 … and so on):

ol {
  counter-reset: item;
  margin: 0;
  padding: 0;
ol>li {
  counter-increment: item;
  list-style: none inside;
ol>li:before {
  content: counters(item, ".") " - ";


This style rule inserts the text “You are here:” before the element with the ID "breadcrumbs":

#breadcrumbs:before {
  content: "You are here:";
  margin-right: 0.5em;


The value of content is either the keyword none, the keyword normal, the keyword inherit, or one or more content specifications (strings, URIs, counters, or quote characters) separated by whitespace.

Using the value normal, we can reset or clear a previously specified content declaration. From an authoring standpoint, there’s no real difference between the values normal and none, except that there’s currently no browser support for none. According to the CSS2.1 specification, if none is specified, the pseudo-element isn’t generated, and if normal is specified for the :before or :after pseudo-elements, it acts like none. Furthermore, if content is specified for other element types, the computed value should aways be normal. However, these kinds of details are targeted towards browser makers rather than CSS authors, so you shouldn’t worry if they’re confusing.

A string value inserts the specified string. If you want a newline character in the generated content, you can use the \a escape, but the generated content is subject to the white-space property, so you’ll need to modify its value for the newline to be rendered as such.

A URI value inserts content read from the specified external resource. The Changes section in the CSS2.1 specification says that this value type has been dropped, but it’s still listed in the normative section for the content property.

A counter value inserts the current value(s) of the specified counter(s). It can be expressed using two different functional notations, both of which have two forms. The counter(name) notation inserts the current value of the counter with the specified name. The counters(name, separator) notation inserts the values of all counters with the specified name, separated by the specified separator string. Both notations also take an optional list style argument (decimal by default) as the last argument, to control the style of the output—for example, counter(item, upper-roman). The keywords available for the list style argument match those available for the list-style-type property.

See counter-reset and counter-increment for details about counters.

The attr(identifier) notation inserts the value of the attribute whose name is specified by the identifier. Note that the argument is an identifier; it shouldn’t be enclosed in quotes.

The open-quote and close-quote values insert the corresponding quotation mark specified in the quotes property. These values also increment or decrement the nesting level for quotes.

The no-open-quote and no-close-quote values don’t insert any content, but they’ll increment or decrement the nesting level for quotes.

See quotes for details about quotes.


Internet Explorer Firefox Safari Opera Chrome
5.5 6.0 7.0 8.0 1.0 1.5 2.0 3.0 3.5 1.3 2.0 3.1 4.0 9.2 9.5 10.0 2.0
None None None Full None Partial Partial Full Full Partial Partial Partial Partial Partial Partial Partial Partial

Internet Explorer for Windows versions up to and including 7 don’t support generated content at all.

Firefox versions up to and including 2, and Opera versions up to and including 10.0 don’t support the value none. Safari versions up to and including 4 and Chrome versions up to and including 3 don’t support the values none or normal. An empty string can be used instead to reset a previous declaration.

In Opera, up to and including version 10:

  • Counters used without a counter-reset have global scope instead of the scope of the elements for which they are used.
  • When the quote nesting level isn’t within the number of pairs defined for the quotes property, open-quote inserts the last-defined close quote character, while close-quote inserts the default close quote character.

Opera, Safari 3+ and Chrome (partially) also support content in contexts other than the :before and :after pseudo-elements. In these cases, the content of the element is replaced by the value of the content property.

Safari versions up to and including 4 and Chrome versions up to and including 3 have no support for the the open-quote and close-quote values.

User-contributed notes

Related Products