Sam Croft

Full-stack developer

Using the CSS content property responsibly without compromising your design and markup


Filed in: css, html, usability

CSS has a wonderful property; content. This property allows extra content to be added to a design directly from your stylesheet. Unlike JavaScript, however, it does not add the extra content to your markup after the DOM has loaded. The content will not appear anywhere in your markup, it only appears in the actual rendering of a page.

The content property can be used to great effect providing it is used responsibly in ways that do not break your page if the content, you are adding via this property, did not exist.

How to use the CSS content property

The content property can only be used in conjunction with the CSS pseudo selectors :before and :after allowing you to add content, in this case a string, before and after a given element. Just like this:

h1:before {
	content: "New!";
	color: #F00;
	margin-right: 10px;

Here I am considering a list of article links, each within an h1 element. Using the :before pseudo selector I am adding some text, ‘New!’, before the article heading using the content property. The real-world use of this particular example would be to prefix the latest article titles with the text, ‘New!’. Obviously there would need to be some additional server side code written to determine which articles were ‘new’, assigning those a class name perhaps and then using the :before pseudo selector to just those titles. But that’s not really what this post is about.

Why not just add the text to the title?

Of course, one could easily just append ‘New!’ to the title itself, or prefix the heading with an inline element such as span that contains ‘New!’. But this creates unnecessary markup that isn’t required. There is no need to actually add ‘New!’ in the markup itself because with or without it, the content makes sense. It isn’t part of a sentence, it doesn’t break the content if it’s missing, nor is it required for SEO or accessibility reasons. It is purely an extra visual cue that an article is ‘new’. If we consider the context of this being a blog, the normal data information would indicate how recent an article was. So in this sense, the additional visual cue is just an extra.

Knowing when and when not to use the CSS content property

For me there are certainly situations when the content property is ideal and definitely when using it would just be plain wrong. I stick to these general guidelines when I consider if I should or shouldn’t use the content property.

Do not use the content property if the content you are adding is required to make sense of whatever your page is displaying.

Do use the content property if the content you are adding is just an additional visual cue.

Do use the content property if you would ordinarily use a background-image, or an image itself, to achieve the same effect.

An easy way to check whether you should or shouldn’t be using the content property is to disable your CSS files temporarily and read the content. Does it still make sense? This is an important check when considering SEO and accessibility.

Some real-world examples of using the CSS content property and why its use makes sense

During the development of RITH’s library based game, Lemontree, I used the content property in several prominent places.

Displaying points scores

One of the primary functions of Lemontree is to show people how many points they have scored in total or per action. An action may be something like; “Sam Croft borrowed The Adventures of Huckleberry Finn and scored 10 points” using the following markup:

	<h1>Sam Croft borrowed The Adventures of Huckleberry Finn</h1>
	<h2>10 points</h2>

The way this is actually rendered on Lemontree is so that it appears like this:

Sam Croft borrowed The Adventures of Huckleberry Finn
+10 points

During development we started out actually having the plus symbol appear within the markup itself, but it was always glaringly obvious that this wasn’t really necessary or correct. This was an ideal situation to use the content property, prefixing each score with the plus symbol. With or without the plus symbol the statement makes complete sense, the plus symbol just adds further weight to the statement that they have been awarded points.

The CSS rule:

h2:before {
	content: "+";
	margin-right: 5px;

Displaying player names and their school/department titles

Lemontree players are not only playing for themselves, they are playing to represent their schools and department, contributing to a school/department leader boards. When viewing an individual player feed the main heading for that page is the players name and their school, using the following markup:

	<h1>Sam Croft</h1>
	<h2>Art, Design and Architecture</h2>

But for the heading appears like this:

Sam CroftArt, Design and Architecture

The em dash is added using the content property. Adding it to the markup itself would be incorrect. Why? Because if it was added directly, where should it be added?

Before the closing of the h1?

<h1>Sam Croft—</h1>
<h2>Design and Architecture</h2>

Pass me the sick bucket.

After the opening of the h2?

<h1>Sam Croft</h1>
<h2>—Design and Architecture</h2>

I’m going to be sick in a minute.

Maybe within a span in between?

<h1>Sam Croft</h1>
<h2>Design and Architecture</h2>

I’ve been sick.

Using the content property:

h2 {
	margin-right: 20px;
h2:before {
	margin-left: -20px;
	content: "—";

That feels better.

What is important here, other than the content property is the use of the margin property. Because the two heading elements will be appearing on the same line, by floating left or displaying inline, I am considering a scenario whereby the user is viewing Lemontree on a browser that does not support the content property. Without the right margin on line 2 the two headings would be bunched right up together. This ensures that there is some space between them for older browsers. For browsers that do support the content property I compensate for the aforementioned right margin by applying a negative left margin to the rule applied with the :before pseudo selector.

About the author

I'm Sam Croft a full-stack developer with over 15 years experience in web and app development. For the last six years I have been a partner of Running in the Halls, an app and game design studio based in Huddersfield, UK. During this time I have developed many web and applications. Highlights include a node.js/ app to create the worlds largest crowd-based game on the first series of Channel 4's Gadget Man with Stephen Fry and Librarygame, a Library gamification platform for Universities. Librarygame is being played by over 6,000 students at The Open University, The University of Manchester, The University of Glasgow and The University of Huddersfield.

In my spare time I enjoy long distance running, watching all sports (especially F1) and playing video games. I live in the Holme Valley in West Yorkshire with my wife, Alex.

Sometimes I tweet.