The content
property is used with the ::before
and ::after
pseudo-elements to generate content that is to be inserted into an element in the page.
The value of the content
property is the content inserted into that element via the pseudo-elements.
The content inserted using the content
property can be string(s) of text, glyphs, images, counters (for styling lists), or quotes. Combining multiple values into one is also possible. See the list of values below and the examples for details.
Note that the content
property must be included in the set of rules for the ::before
and ::after
pseudo-elements, otherwise they won’t be generated and inserted. You have to always include content
. In many cases, it is left empty if you don’t want to add any content and just want to use the pseudo-element for cosmetic use cases. You can read more about different use cases and examples for ::before
and ::after
in their respective entries.
Trivia & Notes
Accessibility
Content inserted into a page using pseudo-elements is not inserted into the DOM—it is only visually displayed. Hence, screen readers won’t be able to access and read the content generated using pseudo-elements. So, it is recommended that you don’t use pseudo-elements to insert vital content into a page (such as footer notes that are relevant to the article, for example).
Pseudo-elements are mostly used to insert and style cosmetic content, and should not be relied on to insert content that is relevant to the meaning and completeness of the content on the page.
Also, since the content inserted using pseudo-elements is not inserted into the DOM, this means that you cannot attach any event handlers to it using JavaScript.
Official Syntax
Values
- none
- No content is inserted. The pseudo-element is not generated.
- normal
-
Computes to
none
for the::before
and::after
pseudo-elements. - <string>
-
A string of text. The string of text is wrapped in quotation marks. See the
<string>
data type entry for a list of possible values.Example: The following add a “New!” note after elements (such as items in a list of products) that have the class
new
..new::after { content: "New!"; color: green; }
You may also include newlines in the generated content by writing the “\A” escape sequence in one of the strings after the
content
property. This inserted line break is still subject to thewhite-space
property. - <uri>
-
The URI is specified using the
url()
function. It points to an external resource such as an image. If the resource or image can’t be displayed, the browser must either leave it out as if it were not specified or display some indication that the resource cannot be displayed.For example, the following adds an icon to buttons with a class
signup
in a page.button.signup::before { content: url(path/to/signup.png); }
- <counter>
-
A CSS Counter. Counters may be specified with two different functions:
counter()
orcounters()
.
See the CSS Counters entry for examples and more information.Example:
li { content: counter(my-counter-name); }
Counters are a fairly long topic and are outside the scope of this entry. For more information, please refer to the the CSS Counters entry.
- open-quote | close-quote
-
These values are replaced by the appropriate string from the
quotes
property. Example:q, blockquote { quotes: "“" "”" "‘" "’"; } q:before, blockquote:before { content: open-quote; } q:after, blockquote:after { content: close-quote; }
For a detailed explanation and more examples refer to the
quotes
property entry. - no-open-quote | no-close-quote
-
Stops the quotes from displaying, but continues to increment (decrement) the level of nesting for quotes. See
quotes
. - attr(X)
-
This function (abbreviation for ‘attribute’) returns as a string the value of attribute X of an element. If the element does not have an attribute X, an empty string is returned.
For example, links
<a>
have anhref
attribute which determines the location to which the link points. Using thecontent
property with theattr()
function you can retrieve the value of the URL in thehref
attribute, which is pretty powerful. This can be used in print style sheets to print the URL to which a link points, right after the content of that link (using the::after
pseudo-element). For example:@media print { a[href]::after { content: attr(href); } }
The above rule selects all links that have an href attribute (using the attribute selector), retrieves the value of the href attribute using the
attr()
function, and then uses that value as the content of the::after
pseudo-element, which will be inserted into the links after the link’s content.The
attr()
function can retrieve the value of any attribute of an element, including custom HTML5 data-* attributes. For example:<li data-label="todo">Buy Milk</li>
li::before { content: attr(data-label); color: grey; }
In CSS3, the
attr()
expression gets a new syntax. The new syntax is not stable, not supported in any browser yet, and there are no examples of use cases anywhere. The specification also says that the new syntax is at risk and may be dropped during the Candidate Recommendation stage. If the new syntax is not dropped, this entry will be updated with the new values. The syntax looks like the following:attr( <attr-name> <type-or-unit>? [ , <attr-fallback> ]? )
where <attr-name> is the attribute name, <type-or-unit> is an optional argument which tells the user agent how to interpret the attribute value, and defines a type for the
attr()
expression. If omitted, ‘string’ is implied. The <attr-fallback> argument represents a fallback value, which is used if the named attribute is missing, or its value cannot be parsed into the given type or is invalid/out-of-range for the property. If it’s absent, the default value for the given <type-or-unit< (from the list below) is implied.The type or unit argument can be one of the following: ‘string’, ‘color’, ‘url’, ‘integer’, ‘number’, ‘length’, ‘angle’, ‘time’, or ‘frequency’.
As mentioned above, this entry will be updated with an elaborated description and examples if the new expression syntax is not dropped in the future.
Notes
It is possible to combine different content values in the content
property. The values are then concatenated into one. For example, the following will retrieve the value of the custom data attribute from the example above, and add a colon after it:
li::before { content: attr(data-label) ":"; color: grey; }
The following example improves the above example where the href
value of a link is retrieved and printed in print style sheets. Printing the URl right after the link content without some visual separators may confuse the reader, so wrapping the URL value in parenthesis is useful and preferred. This can be done by combining the attr()
function with two strings of text for the two parenthesis like so:
@media print { a[href]::after { content: " (" attr(href) ")"; } }
The display
property specifies whether the content inserted is displayed as inline-level or block-level. ::before
and ::after
are displayed inline by default.
Separation of Concerns—Content and Design
In addition to the accessibility issue, some people may argue that adding content via CSS is against the concept of separation of concerns—design and content should be separated to help maintain code better. This may be true in most cases, but it still allows for modular style sheets. For example, the above example where the generated content is used to style links on print style sheets is very useful and can be used in any website by just pasting the snippet into the style sheet.
Other examples such as inserting an “external link” icon to all links in a web page that refer to external pages are also veru useful and modular, and maintaining these styles and content is fairly easy, so the concept of adding content via CSS may be frowned upon by some purists, but it is still useful, and it is up to CSS authors and developers to decide what kind of content to add without affecting the maintainability of their code.
Live Demo
The following live demo shows different content added using the content
property in combination with the ::before
and ::after
pseudo-elements.
You can see these demos and more in the ::before
and ::after
entries.
Browser Support
The content
property is supported in all major browsers: Chrome, Firefox, Safari, Opera, Internet Explorer, and on Android and iOS.