How to Use attr() in CSS for Columns, Colors, and Font-Size

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:

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>

Using attr() for Grid Control

Here’s an example where:

  • data-row explicitly sets what row an element is on
  • data-columns explicitly sets how many columns an element should span
  • data-column-start and data-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.

Using attr() for Colors

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.

Using attr() for Font Sizes

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-names 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 like data-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.

Why always use data-*?

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.

Wanna learn CSS from a course?

2 responses to “How to Use attr() in CSS for Columns, Colors, and Font-Size”

  1. Luke Floden says:

    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!

Leave a Reply

Your email address will not be published. Required fields are marked *

Did you know?

Frontend Masters Donates to open source projects. $363,806 contributed to date.