A more powerful CSS attr() function


The attr() function reads the value of a HTML attribute and allows you to use it in CSS. Values defined in markup can be used within a stylesheet. The attr() function is used most commonly with data- attributes but it can access any HTML attribute. Currently, use of the attr() function is limited to the content property, meaning it can be used with ::before, ::after and ::marker, and is limited to string values.

<ul>
  <li data-mark="💥">item 1</li>
  <li data-mark="✨">item 2</li>
  <li data-mark="🦖">item 3</li>
</ul>
li::marker {
  content: attr(data-mark);
}

Fallback value

attr() supports a fallback value:

h1:before {
  content: attr(data-mark, "✨");
}

This will be used as the default value when the data attribute is not included on the element in your HTML. This has been supported since Firefox 119, Safari Technology Preview 208, and in Chrome Canary (behind a flag).

See the Pen attr() fallback by Ollie Williams (@cssgrid) on CodePen.

(Safari does not yet support the content property for ::marker so the list part of the above demo does not work in Safari.)

attr() for more than string values

In the latest W3C CSS Values and Units specification, the attr() function can be used to specify any kind of value, not just strings, and can be used as the value for any CSS property, not just content.

[data-bg] {
  background-color: attr(data-bg type(<color>));
}
<div data-bg="blue"></div>

To test out the following functionality, open Chrome Canary from terminal with the --enable-features=CSSAdvancedAttrFunction flag (its due to ship in Chrome 133).

/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary --enable-features=CSSAdvancedAttrFunction

See the Pen attr function doesn't work... by Ollie Williams (@cssgrid) on CodePen.

You can combine this new power with fallback values:

div {
  background-color: attr(data-bg type(<color>), pink);
}

See the Pen Untitled by Ollie Williams (@cssgrid) on CodePen.

Here’s an example using the maxlength attribute of an input to set the width:

See the Pen maxlength attribute for width with attr() by Ollie Williams (@cssgrid) on CodePen.

You can set the value of a CSS variable using the attr() function:

See the Pen setting CSS variable with data attribute attr by Ollie Williams (@cssgrid) on CodePen.

If you lose the data- prefix, the HTML will no longer pass validation (but it will still work in all browsers).

Data attributes are easy to update from JavaScript:

someElement.dataset.bg = "purple";

Sadly, it seems that attr() can’t be used in conjunction with the url() function, so code such as the following will not work:

img {
    float: left;
    shape-outside: url(attr(src type(<url>)));
    }

While there’s been a lot of developer interest in attr(), some may be asking: how is this better than inline styles? Or utility classes? How is <div data-bg="blue"> superior to <div class="bg-blue"> or <div style="background-color: blue;">?

A utility class needs to have an explicit value set in a stylesheet. The value of an attr() function can be set to any arbitrary color, any arbitrary size, etc. Much of what you can do with the attr() function can be achieved with an inline CSS variable. However, a Content Security Policy might block inline styles. Inline styles are often avoided because they can only be overridden with !important.