Selective use of CSS content: attr

I’ve been playing around with CSS a lot recently, in particular the content property of the ::before and ::after pseudo-elements. I discovered you can define an HTML attribute and have CSS place it before or after the HTML element on which the attribute is defined.


Let me illustrate with an example.

Example: using content: attr

If I want to show you the contents of a file, I can use a <pre> element of class file-contents. If I define data attribute data-filename inside the <pre class='file-contents'> tag:

<pre class='file-contents' data-filename='example.txt'>The contents of my text file.</pre>

I can use CSS to display that filename:

.file-contents::before {
  content: attr(data-filename); /* no quotation marks or anything */

My sample text file will be displayed like this:

The contents of my named sample text file.

However, the filename might not always be relevant; attribute data-filename will be empty, so the CSS will add an empty string, leading to a blank line; this is undesirable:

The contents of my unnamed sample text file.

Example: using content: attr selectively

To fix this, I can make the CSS rule conditional by inserting the name of the attribute, data-filename, in square brackets after the pre selector [1]; this is an attribute selector, commonly seen used with input tags:

.file-contents[data-filename]::before {
  content: attr(data-filename);

Now, the filename will only show up on elements with the data-filename attribute defined:

The contents of my named sample text file.
The contents of my unnamed text file.


I’m very pleased with myself for discovering this. So much so, that I’ve also added the language of the code snippets as well as filenames – even combining them when relevant. I’ll no doubt add it to anything else I can think of!


  1. CSS content and attr at DWB

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.