The content
property in CSS is used in conjunction with the pseudo-elements ::before
and ::after
. It is used to literally insert content. There are four value types it can have.
String
.name::before {
content: "Name: ";
}
Then an element like this:
<div class="name">Chris</div>
Would render like this:
Name: Chris
It could also be an empty string, which is commonly seen in things like the clearfix.
Counter
div::before {
content: counter(my-counter);
}
Image
div::before {
content: url(image.jpg);
}
This is literally an image on the page like
would be. It could also be a gradient. Note that you cannot change the dimensions of the image when inserted this way. You could also insert an image by using an empty string for the content, making it display: block
in some way, sizing it, and using background-image
. That way you could re-size it with background-size
.
Attribute
You can use values (strings, anyway) that are taken right from attributes in the HTML.
<div data-visual-label="Widget Rating">60</div>
[data-visual-label]::before {
content: attr(data-visual-label) ": ";
}
/* Classic print trick! Show URLs! */
@media (print) {
a[href]::after {
content: " (" attr(href) ") "; /* you could combine a url() in here even if you wanted */
}
}
The attr()
function doesn’t have “types” just yet, so you can’t pass a value like 20px
(just strings), but someday!
Alternative Text
The spec says that you can use a /
in the syntax to list alternate text. For example…
.el::before {
content: "⭐️" / "Alternate Text for that star";
content: "→" / ""; /* Visual only, don't read. */
}
Perhaps you could use it like…
<ul aria-label="To Do List">
<li>Make Bed</li>
<li data-alt-pseudo="Completed">Grocery Shop</li>
<li>Sweep Driveway</li>
</ul>
[data-alt-pseudo="Completed"]::before {
content: "✅"; /* fallback */
content: "✅" / attr(data-alt-pseudo);
}
More Information
Content inserted in this way isn’t really in the DOM, so it has some limitations. For instance, you can’t attach an event directly (only) to pseudo-elements. It is also inconsistent whether or not text inserted in this way is read by screen readers (it usually is these days) or if you can select it (it usually isn’t these days).
Browser Support
This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.
Desktop
Chrome | Firefox | IE | Edge | Safari |
---|---|---|---|---|
4 | 2 | 9 | 12 | 3.1 |
Mobile / Tablet
Android Chrome | Android Firefox | Android | iOS Safari |
---|---|---|---|
123 | 124 | 2.1 | 3.2 |
For Opera, url()
only supported in version 7+.
…holy gumballs batman you can use counters!? And just when I think I know everything there is to know about CSS…
If only
attr()
had greater browser support for it’surl
<type-or-unit>
keyword:http://jsbin.com/ujeyok/1/edit
True ! I’m waiting for it too. We could do a lot with this.
True ! I’m waiting for it too.
A great use of this would be print stylesheets. You show the URL beside links.
HTML
CSS
Woah, the counter and the attribute method is really powerful. Till now I just used this to create special elements to add visual effects
Any suggestions on how to add an image using css and make it 100% width and keep it proportional as the window changes? I was trying :before with a url which got me here, but I seem to be rather stuck.
Have you tried
background-size: cover
, as seen in this article?Can we combine
content: url(image.jpg);
widthcontent: attr(data-image);
?Something like this
url(attr(data-image));
I just want to mention that I certainly enjoyed you’re page. Likely I’m planning to bookmark your site . You really come with amazing articles. With thanks for sharing with us your blog site.
“content: url(image.jpg);” Doesn’t work nicely on firefox.
See the CodePen below: http://codepen.io/IgnaciodeNuevo/pen/PqwVQe
I want to add an asterisk, as in the image on the left to the input on the right.
I am completely stuck and it’s stupid that I don’t see.
Just add a span around your input element and give it the asterisk class instead of the input. Since ::before + ::after add the content before/after the elements own content and input elements don’t have content, your example doesn’t work.
Did not see this mentioned in the comments….
Raster images (png, jpg, gif) won’t scale in the content of :before|:after but, an svg DOES scale based on the box size.
Of course the SVG has to be responsive.
You can if you give it ‘display:block’ or ‘display:inline-block’ (or probably some other display values other than ‘inline’). Or if you float it, or absolute position it.
Cool thing!
I just want to know how we can make the text in content property to be displayed as two or more line, for example:
.before { content: “line 1 line 2 line 3”};
then it will displayed as:
line 1
line 2
line 3
Thanks
content: “line 1 \a line 2 \a line 3”; should do the trick
\a is the “content “newline sequence.
content: “line 1 \a line 2\a line 3”
\a is the “content” newline code
Hey! I am not able to change the width and height of the image by using :before. Could you please help me?
You can scale an image with
transform
.You could scale the image with transforms… sorry late to the party…