-
Notifications
You must be signed in to change notification settings - Fork 33
attr() support extended capabilities (Interop 2023) #86
Description
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
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/,' | uniq
wpt.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
- Many great arguments voiced in this Chromium Dev thread (246571)
attr()is more semantic — avoiding forcing styles into the markup using CSS custom properties as a workaround- avoiding redundancy — using CSS custom properties instead of being able to use
attr()properly often requires addtl setup within markup simply to allow value exposure to CSS - would make data management more achievable in copywriting stage where editors work more predominantly with markup than they do inline styling
Supporting examples
Click to expand relevant example
A11Y labels (tooltip example)
❌ 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>
```
<type-or-unit> (units example)
❌ 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>
```
background-image (url example)
❌ w/o extended attr() features — using data- attr workaround (not possible without CSS custom properties)
<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>❌ w/o extended attr() features — using CSS custom properties workaround
<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>✅ w/ extended attr() features
<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>