I’ve personally put “advanced attr()
usage” on my CSS wishlists for years and years. All the sudden we’re seeing support for it start to drop! Props to the Chrome gang and others for shipping and highlighting this wonderfulness. I’m avoiding being entirely comprehensive about this feature in this post, so it’s worth perusing other coverage:
- Una Kravets: New capabilities for attr()
- Bramus Van Damme: CSS attr() gets an upgrade
- MDN attr() docs are updated.
- Amit Merchant: The attr() function in CSS now supports types
I thought I would chime in with my own examples so help smash it into my brain and to create an easy reference for soon to be classic use cases.
The Deal
The value of attr()
used to be always a string, which made the value pretty much only useful for the content
property and certain niche text effects.
div::after {
content: attr(data-title);
}
Code language: CSS (css)
Even if you put something like data-number="10"
, you could never get a proper number 10 to use in CSS. The same with like data-size="3rem"
, no chance of actually getting 3rem
to actually use.
Now you can! You just have to declare what type it will be.
div {
font-size: attr(data-font-size type(<length>));
grid-column-start: attr(data-column-start type(<integer>));
/* example with a "fallback" */
color: attr(data-color type(<color>), black);
}
Code language: CSS (css)
This usage is Chrome-only as I write/publish here, but that will change over time.
Types
<string>
<angle>
<color>
<custom-ident>
<integer>
<length>
<length-percentage>
<number>
<percentage>
<resolution>
<time>
<transform-function>
attr()
for Grid Control
Using Here’s an example where:
data-row
explicitly sets what row an element is ondata-columns
explicitly sets how many columns an element should spandata-column-start
anddata-column-end
set on where a column should start or end
That’s just one possible implementation where you essentially define your own API for what you want to allow and how you want to apply it.
attr()
for Colors
Using Just naming a color you want to use is nice!
This example highlights a nicety of having the additional “layer” of CSS to handle things, as opposed to very direct inline styles. Here I’m not just setting one color, but I’m using the color given for the actual color
, then taking that same color and color-mix()
ing in some black to use as the background color.
To highlight the control you have even more, we could use min()
and max()
values within the relative color syntax to ensure, for example, the color has a minimum level of brightness that we might think is best for readability.
Above the dot before each line is the actual color being set as an attribute, but then when we use it to color a word in the line, we’re converting the color to oklch()
and ensure the “l” part (lightness) has a minimum value of 0.9
(with max(l, 0.9)
) to ensure that.
attr()
for Font Sizes
Using Setting a data-font-size
is easy peasy. But here I’ll jump forward to the “extra control” part right away. Perhaps your design system has strong rules about font sizing and you only allow increments of 5px. Using CSS round()
we could make that happen with this approach.
Others?
- How about
data-gap
as a utility to just change the gap, but be able to round it to particular values in a design system? - How about automatic
view-transition-name
s like Bramus did up. - One-off borders with a
data-border
seems like nice control to offer. Or even individual borders. Or individual parts of individual borders likedata-border-bottom-width
. - It occurs to me that setting the value of a custom property to the attribute value is a way of passing the value lower in the DOM tree, which doesn’t seem possible otherwise, like…
[data-button-color] {
--button-color: attr(data-button-color type(<color>));
button {
color: var(--button-color);
}
}
Code language: HTML, XML (xml)
With that it seems like you could do stuff like data-size-of-close-button
on a <dialog>
and then access that informaton wherever you implement the close button within there.
data-*
?
Why always use You don’t have to. I just like the idea of not polluting attribute names. If the web platform one day really really wanted to support a gap
attribute for whatever reason, but found through analyzing websites that too many websites rawdogged it already because of this feature, that would be a bummer to me. The data-*
namespace was created just for this reason, so we might as well use it. Plus you get the JavaScript dataset
property to use for free if you do.
ok bye and please shower me with more ideas for this.
I rushed over to codepen to convert your color demo to oklch and the from syntax before seeing you did that for your very next demo!
haha YES