❌ w/o extended `attr()` features — using `data-` attr workaround
```html
<button
aria-label="Some label here"
data-label="Some label here"
>
Button
</button>
<style>
button:hover::after,
button:focus::after {
/* FALLBACK VALUE NOT SUPPORTED */
content: attr(data-label);
}
</style>
```
❌ w/o extended `attr()` features — using CSS custom properties workaround
```html
<button
aria-label="Some label here"
style="--label: 'Some label here'"
>
Button
</button>
<style>
button:hover::after,
button:focus::after {
content: var(--label, "default label");
}
</style>
```
✅ w/ extended `attr()` features
```html
<button aria-label="Some label here">Button</button>
<style>
button:hover::after,
button:focus::after {
content: attr(aria-label, "default label");
}
</style>
```
❌ w/o extended `attr()` features — using `data-` attr workaround
```html
<div data-size="100" style="width: 100px; height: 100px;"></div>
<style>
div {
background-color: cyan;
/* VALUE TYPE-CASTING NOT SUPPORTED */
}
div::after {
content: "Size: " attr(data-size);
}
</style>
```
❌ w/o extended `attr()` features — using CSS custom properties workaround
```html
<div style="--size: 100px; --size-label: '100';"></div>
<style>
:root {
/* Coupling variables creates risk of mismatched values */
--fallback-size: 50px;
--fallback-size-label: "50";
}
div {
background-color: cyan;
/* VALUE TYPE-CASTING NOT SUPPORTED */
width: var(--size, var(--fallback-size));
height: var(--size, var(--fallback-size));
}
div::after {
content: "Size: " var(--size-label, var(--fallback-size-label));
}
</style>
```
✅ w/ extended `attr()` features
```html
<div data-size="100"></div>
<style>
:root {
--fallback-size: "50";
}
div {
background-color: cyan;
width: attr(data-size px, var(--fallback-size));
height: attr(data-size px, var(--fallback-size));
}
div::after {
content: "Size: " attr(data-size, var(--fallback-size));
}
</style>
```
<div
data-image="/images/background.jpg"
style="--image: url('/images/background.jpg');"
></div>
<style>
div {
background-image: var(--image);
}
div::after {
content: "Image filepath: " attr(data-image);
}
</style>
<div
style="
--image-filepath: '/images/background.jpg';
--image: url('/images/background.jpg');
"
></div>
<!-- ** important to note here that interpolating the value of `--image-filepath` into `--image` is not yet supported in CSS custom properties, so `--image: url(var(--image-filepath))` would not work -->
<style>
div {
background-image: var(--image, none);
}
div::after {
content: "Image filepath: " var(--image-filepath, 'no file present');
}
</style>
<div data-image="/images/background.jpg"></div>
<style>
div {
background-image: attr(data-image url, '');
}
div::after {
content: "Image filepath: " attr(data-image, 'no file present');
}
</style>
Description
The attr() CSS function is used to retrieve the value of an attribute of the selected element and use it in the stylesheet. It can also be used on pseudo-elements, in which case the value of the attribute on the pseudo-element's originating element is returned. (MDN)
Specification
CSS Values and Units Module Level 5
# attr-notation
Tests
wpt / css / q: css-values
More tests courtesy of @karlcow (from comment below) using…
find css -type f | xargs grep 'attr(' | sort | grep -v 'ref.html' | grep -v '.py' | sed 's,\:.*,,' | sed 's,^,https://wpt.fyi/,' | uniqwpt.fyi/css/css-align/self-alignment/self-align-safe-unsafe-flex-001.html
wpt.fyi/css/css-align/self-alignment/self-align-safe-unsafe-flex-002.html
wpt.fyi/css/css-align/self-alignment/self-align-safe-unsafe-flex-003.html
wpt.fyi/css/css-align/self-alignment/self-align-safe-unsafe-grid-001.html
wpt.fyi/css/css-align/self-alignment/self-align-safe-unsafe-grid-002.html
wpt.fyi/css/css-align/self-alignment/self-align-safe-unsafe-grid-003.html
wpt.fyi/css/css-conditional/at-supports-namespace-001.html
wpt.fyi/css/css-content/attr-case-sensitivity-001.html
wpt.fyi/css/css-content/attr-case-sensitivity-002.html
wpt.fyi/css/css-content/attr-case-sensitivity-003.html
wpt.fyi/css/css-gcpm/string-set-012.html
wpt.fyi/css/css-values/attr-color-invalid-cast.html
wpt.fyi/css/css-values/attr-color-invalid-fallback.html
wpt.fyi/css/css-values/attr-color-valid.html
wpt.fyi/css/css-values/attr-in-max.html
wpt.fyi/css/css-values/attr-invalid-type-001.html
wpt.fyi/css/css-values/attr-invalid-type-002.html
wpt.fyi/css/css-values/attr-invalid-type-008.html
wpt.fyi/css/css-values/attr-length-invalid-cast.html
wpt.fyi/css/css-values/attr-length-invalid-fallback.html
wpt.fyi/css/css-values/attr-length-valid-zero-nofallback.html
wpt.fyi/css/css-values/attr-length-valid-zero.html
wpt.fyi/css/css-values/attr-length-valid.html
wpt.fyi/css/css-values/attr-px-invalid-cast.html
wpt.fyi/css/css-values/attr-px-invalid-fallback.html
wpt.fyi/css/css-values/attr-px-valid.html
wpt.fyi/css/css-values/calc-rgb-percent-001.html
wpt.fyi/css/css-variables/variable-generated-content-dynamic-001.html
wpt.fyi/css/cssom/css-style-attr-decl-block.html
wpt.fyi/css/cssom/serialize-values.html
Rationale
This has been a highly anticipated feature for several years and would do a great deal to equip developers to utilize values defined in markup within their styles. The workaround thus far has been to exclude these values within CSS custom properties (variables), but that often requires having values in two places— (1) an attribute for proper syntax for a given element and (2) a CSS custom property for usage within stylesheets. but for many, especially non-devs who simply work with HTML, this
Supporting rationale
attr()is more semantic — avoiding forcing styles into the markup using CSS custom properties as a workaroundattr()properly often requires addtl setup within markup simply to allow value exposure to CSSSupporting examples
Click to expand relevant example
A11Y labels (tooltip example)
<type-or-unit>(units example)background-image (
urlexample)❌ w/o extended
attr()features — usingdata-attr workaround (not possible without CSS custom properties)❌ w/o extended
attr()features — using CSS custom properties workaround✅ w/ extended
attr()featuresCurrent Browser Compatibility (view on MDN)
Expand to see screenshot of CSS
attr()browser compatibility chart (from MDN)