惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
GRAHAM CLULEY
S
Security @ Cisco Blogs
P
Proofpoint News Feed
Cisco Talos Blog
Cisco Talos Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tor Project blog
WordPress大学
WordPress大学
Project Zero
Project Zero
S
Schneier on Security
P
Proofpoint News Feed
小众软件
小众软件
P
Privacy International News Feed
美团技术团队
L
LangChain Blog
Know Your Adversary
Know Your Adversary
J
Java Code Geeks
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The Register - Security
The Register - Security
N
Netflix TechBlog - Medium
Microsoft Security Blog
Microsoft Security Blog
Engineering at Meta
Engineering at Meta
I
InfoQ
量子位
Vercel News
Vercel News
博客园 - 三生石上(FineUI控件)
Spread Privacy
Spread Privacy
D
DataBreaches.Net
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
U
Unit 42
P
Privacy & Cybersecurity Law Blog
C
Cybersecurity and Infrastructure Security Agency CISA
T
The Blog of Author Tim Ferriss
Latest news
Latest news
K
Kaspersky official blog
MongoDB | Blog
MongoDB | Blog
L
LINUX DO - 热门话题
Simon Willison's Weblog
Simon Willison's Weblog
云风的 BLOG
云风的 BLOG
S
Securelist
AWS News Blog
AWS News Blog
F
Fortinet All Blogs
T
Threat Research - Cisco Blogs
Stack Overflow Blog
Stack Overflow Blog
Scott Helme
Scott Helme
Help Net Security
Help Net Security
Y
Y Combinator Blog
宝玉的分享
宝玉的分享
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
Tenable Blog

Ahmad Shadeed

Better fluid sizing with round() Use Cases for Field Sizing The Basics of Anchor Positioning Item Flow CSS Relative Colors Balancing Text In CSS Should masonry be part of CSS grid? CSS display contents CSS Grid Areas CSS Cap Unit An Interactive Guide to CSS Container Queries CSS :has() Interactive Guide CSS Nesting UX in DevTools CSS Nesting Future CSS: State Container Queries Rebuilding a comment component with modern CSS Conditional CSS with :has and :nth-last-child CSS Text balancing with text-wrap:balance CSS Masking Do we need CSS flex-wrap detection? My CSS Wishlist Conditional CSS CSS Style Queries Inside the mind of a frontend developer: Article layout Inside the mind of a frontend developer: Hero section CSS container queries are finally here The CSS behind Figma First Look At The CSS object-view-box Property Learn CSS Subgrid CSS :has Parent Selector Aligning Content In Different Wrappers Flexbox Dynamic Line Separator Hello, CSS Cascade Layers Building UI Components With SVG and CSS A Deep CSS Dive Into Radial And Conic Gradients Defensive CSS Building Real-life Components: Facebook Messenger Conditional Border Radius In CSS CSS Container Query Units Aligning a Button Label Vertically Comparing Design Mockups To Code Result Using HSL Colors In CSS Custom Scrollbars In CSS Let CSS Container Queries For Designers The State of CSS Cross-Browser Development Overflow Issues In CSS Inspect Element As A Way To Increase Your Curiosity Handling Text Over Images in CSS Digging Into CSS Logical Properties Clipping Scrollable Areas On The inline-start Side Understanding Clip Path in CSS The Art of Building Real-life Components Handling Short And Long Content In CSS CSS Scroll Snap A Deep Dive Into CSS Grid minmax() CSS Variables 101 Finding The Root Cause of a CSS Bug Learn CSS centering How to detect browser support for Flexbox Gap CSS Mistakes While On Autopilot Digging Into the Flex Property Understanding CSS Multiple Backgrounds Aligning Logo Images in CSS Grid for layout, Flexbox for components Colors in CSS Thinking About The In-between Design Cases min(), max(), and clamp() CSS Functions Image Techniques On The Web Everything About Auto in CSS Learn Box Alignment Let Learn CSS Positioning Intrinsic Sizing In CSS CSS Grid Template Areas In Action Hiding Elements On The Web Creating a Variable Color Font From Scratch Building a Football Ticket With CSS and SVG Blending Modes in CSS CSS Variables With Inline Styles Implementing Dark Mode For My Website Rebuilding Apple Music Header in HTML & CSS Accessible Checkbox Layout Flickering On Browser Resize Enhancing The Clickable Area Size Custom Underlines with SVG Part 3: The Process of Implementing A UI Design From Scratch Part 2: The Process of Implementing A UI Design From Scratch Building An Old Nav Design CSS Flexbox: 5 Real World Use Cases I Used CSS Inline Flex For The First Time The Process of Implementing A UI Design From Scratch Common CSS Issues For Front-End Projects Handling Long and Unexpected Content in CSS How to Build Web Form Layouts With CSS Grid Grid Layout Ah-ha Moment Enhancing Our Components with CSS :empty Building Resizeable Components with Relative CSS Units CSS Writing Mode The Journey of Learning Front End Web Development on a Daily Basis
First Look at The Modern attr()
Ahmad Shadeed · 2025-04-03 · via Ahmad Shadeed

The Layout Maestro

I spent years teaching CSS layout on this blog. I put everything I know into The Layout Maestro course: 70+ lessons and 150+ interactive examples that teach you how to think CSS layouts, not just memorize syntax.

Get the course

Intro

You might have used the attr() function in CSS before to get the text content for a pseudo-element.

<p data-title="This text is before the title">Hello World</p>
.title:before {
  content: attr(data-title);
}

The result is as follows:

CSS is awesome

There is nothing new or groundbreaking here, it’s useful for some cases.

However, when we want to use a value other than text, it will not work. In the following HTML, I added data-color attribute to the p element.

<p data-color="red">CSS is awesome</p>

And then used the attribute in CSS.

.title:before {
  color: attr(data-color);
}

It’s not working because the attr() function only supports text values.

CSS is awesome

attr()

Limited availability

Supported in Chrome: no. Supported in Edge: no. Supported in Firefox: no. Supported in Safari: no.

This feature is not Baseline because it does not work in some of the most widely-used browsers.

attr() on Web Platform Status

Now, we can use attr() and define the type of value we want to use.

The attr syntax

For example, in this case, we need to get the color value.

<p data-color="red">CSS is awesome</p>
.title:before {
  color: attr(data-color type(<color>));
}

CSS is awesome

According to MDN, the new data type can take different value types:

The type() function takes a <syntax> as its argument that specifies what data type to parse the value into. The <syntax> can be <angle>, <color>, <custom-ident>, <image>, <integer>, <length>, <length-percentage>, <number>, <percentage>, <resolution>, <string>, <time>, <transform-function>, or a combination thereof.

That gives us a lot of new flexibility that we didn’t have before. Where that might be useful? That’s what I will explore in this article.

Feature detection

We can check for the modern attr() support with CSS @supports. Here is an example:

@supports (x: attr(x type(*))) {
  /* modern attr() works */
}

If you are using Sass, the above won’t be parsed. I escaped it to make it work in .scss files:

@supports (#{"x: attr(x type(*))"}) {
  /* modern attr() works */
}

Use cases for the modern attr()

Assign column numbers

When using a CSS grid, we can assign column numbers to each child of the grid.

In this example, I defined data-col-start and data-col-end on a grid item to set the start and end of the column.

In CSS, I can retrieve the numbers like so:

.layout {
  > * {
    grid-column-start: attr(data-col-start type(<number>), 2);
    grid-column-end: attr(data-col-end type(<number>), 3);
  }
}

If the attribute isn’t set, it will fall back to 2 and 3 as I specified. Play with the following demo and see how it works:

<div data-col-start="1" data-col-end="-1">

<img src="desk.jpg" alt="" />

</div>

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quam deleniti officia aut nulla vero cumqu.

Veritatis, tempore itaque accusamus alias voluptate illum cupiditate eius incidunt et laudantium?

If the attributes are not set, the grid-column-start and grid-column-end will default to the fallback values.

See the following demo:

<div data-col-start="1" data-col-end="-1">

<img src="desk.jpg" alt="" />

</div>

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quam deleniti officia aut nulla vero cumqu.

Veritatis, tempore itaque accusamus alias voluptate illum cupiditate eius incidunt et laudantium?

Access textarea rows

We can use the rows attribute and multiply it by a threshold number.

textarea {
  min-height: calc(attr(rows type(<number>)) * 50px);
}

Check out the demo below:

<textarea rows="3"></textarea>

Write a brief description about your product idea:

Animation delay

Another great usage of modern attr() is to delay an animation. Since attr() works with the <time> type, we can take this to our advantage.

In the following HTML, we have a list of items. Each item has a data-delay attribute. We can take this and use it in CSS.

<div class="itemsWrapper">
  <div class="item" data-delay="0.3s"></div>
  <div class="item" data-delay="0.6s"></div>
  <div class="item" data-delay="0.9s"></div>
  <div class="item" data-delay="1.2s"></div>
</div>

To use the value, we need to call the attribute and then define its type. If not defined, it will fall back to a default delay of 0.5s.

See the following CSS:

.item {
  animation-delay: attr(data-delay type(<time>), 0.5s);
}

Here is an interactive demo that shows how it works:

<div class="itemsWrapper">

<div class="item" data-delay="0.3s"></div>

<div class="item" data-delay="0.6s"></div>

<div class="item" data-delay="0.9s"></div>

<div class="item" data-delay="1.2s"></div>

</div>

Color tint

By having a unique number for each html element, we can use it to change the color lightness as per its index.

In this example, I’m using the data-index attribute to get the value for lightness while using CSS relative colors.

.item {
  background-color: oklch(
    from #ab4ef8 calc(l + calc(attr(data-index type(<number>)) / 20)) c h
  );
}

Check the demo below:

<div class="itemsWrapper">

<div class="item" data-index="1"></div>

<div class="item" data-index="2"></div>

<div class="item" data-index="3"></div>

<div class="item" data-index="4"></div>

<div class="item" data-index="5"></div>

<div class="item" data-index="6"></div>

<div class="item" data-index="7"></div>

</div>

In that regard, we now have sibling-index in the works! Exciting times.

Grid gap

I used attr() to define the value of grid-gap. What’s nice here is that we can define multiple options for the value. In this case, I defined the types <length> or <percentage>.

.layout {
  gap: attr(data-gap type(<length> | <percentage>));
}

Try to change the length values in the below demo:

<div class="layout" data-gap="1rem"></div>

Grid template areas

One of the powerful features of CSS grid is using grid named areas. I thought about why not trying to define the grid template area with data attributes?

At first, I tried the following:

<div
  class="layout"
  data-areas="'featured item-1' 'featured item-2' 'item-3 item-4'"
></div>

Though it didn’t work. I think it’s invalid CSS (Please correct me if I’m wrong). To make it work, I’ve to define each row individually as the following:

<div
  class="layout"
  data-row-1="featured item-1"
  data-row-2="featured item-2"
  data-row-3="item-3 item-4"
></div>

Then, I used that in CSS like so. Notice that I didn’t define the type since the default is <string>.

.layout {
  grid-template-areas:
    attr(data-row-1)
    attr(data-row-2)
    attr(data-row-3);
}

Here is a demo that shows it in action:

Featured

Item 1

Item 2

Item 3

Item 4

<div class="layout"

data-row-1="featured item-1"

data-row-2="featured item-2"

data-row-3="item-3 item-4">

</div>

Background images

An example of where we can use attr() is with background images. Usually, when we have a dynamic background that is set via JavaScript, we tend to set background-image on each element or use a CSS variable.

We can set an attribute and use that in CSS. It gives the same result as using the inline CSS variable, but it feels cleaner to me.

<!-- Inline CSS Variable -->
<div style="--bg: linear-gradient(45deg, #9c3ce7,#3d53cc)"></div>

<!-- The new attr() -->
<div data-bg="linear-gradient(45deg, #9c3ce7,#3d53cc)"></div>

In CSS, we can use it like so:

.element {
  background: attr(data-image type(<image>)) no-repeat;
}

<div data-bg="linear-gradient(45deg, #9c3ce7, #3d53cc)"></div>

Progress bar

In this demo, I wanted to see how the attr() will work when used in a CSS variable. I defined data-color and data-progress on the main container.

<div class="bar" data-color="#a548e3" data-progress="55">
  <div class="bar__current"></div>
</div>

Then, in CSS, I:

  • defined a progress variable to get the unitless value.
  • defined a color variable to store the color. I
.bar {
  --progress: attr(data-progress type(<number>));
  --color: attr(data-color type(<color>));
  background-color: oklch(from var(--color) calc(l + 0.35) c h);
}

.bar__current {
  width: calc(var(--progress) * 1%);
  background-color: oklch(from var(--color) l c h);
}

It works! Here is a demo:

<div class="bar" data-color="#a548e3" data-progress="55"></div>

<div class="bar" data-color="#afe348" data-progress="75"></div>

<div class="bar" data-color="#e38148" data-progress="40"></div>

If we compare this to the approach of using an inline CSS variable, it will quickly become harder to read/scan.

<!-- Inline CSS Variable -->
<div class="bar" style="--color: #a548e3; --progress: 55"></div>

<!-- Modern Attr -->
<div class="bar" data-color="#a548e3" data-progress="55"></div>

A Mini CSS framework?

I had an idea in mind when I first started exploring attr() and I’m glad it’s not just me.

What if we can use attr() to have a mini CSS framework or utility classes to be used within a system? In the following snippet, I added px which stands for the padding on the horizontal sides.

<div px="1rem"></div>

In CSS, I need to define this only once:

[px] {
  padding-inline: attr(mx type(<length));
}

And I can use it on many elements as needed:

<div px="1rem"></div>
<div px="10px"></div>
<div px="0"></div>

I defined the CSS once and reused the utility attribute multiple times. Isn’t that cool? I took this further and built a bit more attributes:

Some content in here

Some content in here

<div

max-w="500px"

px="1rem"

py="1rem"

bg-color="#fff"

color="#222">

</div>

<div

max-w="300px"

px="2rem"

py="2rem"

bg-color="var(--brand-1)"

color="#fff">

</div>

Multi value attr is useful

When I published this article, I had the understanding that we can’t use keywords like auto. Turned out, it’s possible to do this with the type <custom-ident>. Thanks to Temani Afif, I learned that it’s possible.

I wish that there was a way to have a “keyword” type. For example, If I have an attribute that could be a length value or an auto, I need to allow multiple values.

[mx] {
  margin-inline: attr(mx type(<length> | <custom-ident>));
}
<div mx="auto"></div>

Or we can use a length value:

<div mx="2rem"></div>

Also, we can use the universal selector to make it accept any value.

[mx] {
  margin-inline: attr(mx type(*));
}

Another idea is to allow either a length type or the auto keyword. Thanks to Bramus and Dannie Vinther for suggesting this.

[mx] {
  margin-inline: attr(mx type(<length> | auto));
}

Why use modern attr() over inline CSS?

Javascript usage

When using data-* for an attribute name, we can access it by using dataset. If we have an attribute data-color, we can do the following:

element.dataset.color = "blue";

Separation of concerns

When using modern attr(), we can separate the content from the styling and so making the HTML easier to scan.

<!-- Inline CSS Variable -->
<div class="bar" style="--color: #a548e3; --progress: 55"></div>

<!-- Modern Attr -->
<div class="bar" data-color="#a548e3" data-progress="55"></div>

Reduces CSS conflicts

When using data attributes, it’s not possible to mess up with CSS. We can have an API-like way to style our pages. In a design system, using attr() can prevent the developers from accidentally overwriting styles and it makes the CSS more predictable.

Conculsion

Modern attr() provide us with a powerful way write CSS based on data attributes. At the time of writing, it’s Chrome only and I wish more browsers will follow soon.

Further resources