On this page:
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.
What?!
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.
Conclusion
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!