The CSS attr()
function is getting updated to support any property.
This enables the creation of configurable CSS components, which allow content creators to specify properties directly, using custom tags and attributes.
This article showcases three examples: a gradient text, an underline, and a fade-out component. While the new attr()
syntax is not yet supported in browsers, custom properties can be used as a fallback.
With the current implementation, the attr()
-function can set the content
-attribute of a pseudo-element (::before
or ::after
) from a HTML-attribute.
After the update, attr()
works with all properties, not just content
.
It will also support types and fallbacks, so you can define a property as, let's say, a color, and specify the fallback-color, if the property is empty:
color: attr(data-cl color, #DC143C);
What does that mean?
While this may not seem like a groundbreaking change, it is (at least for for me!)
Imagine a headline like this:
It consists of a gradient text, a custom underline and a fadeout.
To allow a content-creator to specify the gradient-text colors, the height or color of the underline — or the angle of the fade-out, would require loads of modifier-classes and extra CSS to maintain.
But with the ability to set a property directly (with failsafe types) using attr()
, we can create configurable CSS components.
Let's create a bunch — starting with <gradient-text>
:
Gradient Text
First, we create a custom tag, <gradient-text>
with two attributes, from
and to
:
<gradient-text from="#06d" to="#0fd">
For the CSS, it's simply:
gradient-text {
background: linear-gradient(
attr(angle angle, 135deg),
attr(from color, #8E6BC8),
attr(to color, #00E9EE)
);
background-clip: text;
-webkit-background-clip: text;
box-decoration-break: clone;
-webkit-box-decoration-break: clone;
color: transparent;
}
You can use the custom tag today, but it won't work with the new attr()
, as it's not supported in any browsers yet.
We need a fallback, using @supports
:
gradient-text {
@supports( color: attr(data-c color, red)) {
--angle: attr(angle angle, 135deg);
--from: attr(from color, #8E6BC8);
--to: attr(to color, #00E9EE);
}
background: linear-gradient(
var(--angle, 135deg),
var(--from, #8E6BC8),
var(--to, #00E9EE)
);
/* ... */
}
First, we check whether the new attr()
-syntax is supported. If it is, we're setting a bunch of custom properties to the attribute-values. Then, outside the fallback, we'll use these properties for the gradient.
Examples:
<gradient-text from="#06d" to="#0fd">
— and with the optional angle
-attribute:
<gradient-text from="#06d" to="#0fd" angle="190deg">
Underline
The <under-line>
-component is almost identical to the <gradient-text>
-component. It has a from
and a to
-attribute, but if you don't specify to
, it's set to from
. Instead of angle
, it has a height
-attribute.
Examples:
<under-line from="#27D2C6" to="#9FFFF9">
— and —
<under-line from="#fcd4ff" height="10%">
Which gets us:
The CSS follows the same structure as before, with a @supports
-fallback first:
under-line {
@supports( color: attr(data-c color, red)) {
--from: attr(from color, #FCD4FF);
--to: attr(to color, #FCD4FF);
--height: attr(height length, 25%);
}
background-image: linear-gradient(
90deg,
var(--from, #FCD4FF),
var(--to, var(--from, #FCD4FF))
);
background-position: left bottom;
background-repeat: no-repeat;
background-size: 100% var(--height, 25%);
}
Fadeout
Like the previous components, the <fade-out>
-component have a from
and a to
-attribute.
fade-out {
@supports( color: attr(data-c color, red)) {
--angle: attr(angle angle, 90deg);
--from: attr(from %, 50%);
--to: attr(to %, 100%);
}
--mask: linear-gradient(
var(--angle, 90deg),
#000 var(--from, 50%),
#0000 var(--to, 100%))
0vw 0vw no-repeat;
-webkit-mask: var(--mask);
mask: var(--mask);
white-space: nowrap;
}
Examples:
<fade-out from="50%" to="100%">
— and with optional angle
-attribute:
<fade-out angle="180deg" from="0%" to="90%">
Which gets us:
Conclusion
In conclusion, the introduction of the updated attr()
-function in CSS, opens up new possibilities for creating configurable CSS components.
As we've seen in the examples, content creators can easily specify properties such as colors, heights, and angles without the need for extra CSS or modifier classes.
Although the new attr()
syntax is not yet supported in any browsers, we can use custom tags with fallbacks using the @supports
rule to achieve similar effects.
If you want to use the custom tags from the examples today, you need to update the custom properties (--to
, --from
etc.) instead of using attributes.
You can do this with modifier-classes, or write a small JavaScript-snippet, that'll set the custom properties from the attributes, so:
<gradient-text from="#06d" to="#0fd">
becomes:
<gradient-text style="--from:#06d;--to:#0fd">
Cover Photo by Alexander Grey
Top comments (2)
Are you able to test this in any browsers (even with flag enabled)?
attr()
are defined to work with any property since too long (An example I remember from 2019: stackoverflow.com/q/56613889/8620333) but 0 browser support 😞No, not a single one, I’m afraid! Hence all the fallback-stuff.
But MDN has an example with
background-color
being set from an attribute, that I didn’t see earlier — that’s what triggered me, since I had to do these components for a website.