47

I have this in my HTML document:

<a class="wbutton tint" data-tint="rgba(255,0,0,.5)" href="#">This should be red, with an opacity of 0.5</a>

and this in the CSS file:

.window > .content .wbutton.tint {
    border: solid thin attr(data-tint, color);
    box-shadow: inset 0 0 50px attr(data-tint, color);
}

Firefox returns a CSS error in Firebug. Am I doing something wrong?

According to the W3C specs for the attr() function, it should work.

(Also, there's a page about attr() in the MDN Wiki, so I assume it should at least work in Firefox)

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Peter W.
  • 2,323
  • 4
  • 22
  • 42
  • 1
    I'm pretty sure "attr()" is not part of CSS3, or any other CSS, even if it, CSS3 is still a draft, and even the very latest browsers don't have full support yet. – GManz Jan 07 '12 at 13:09
  • 2
    @Hosh Sadiq: It is. See my answer. – BoltClock Jan 07 '12 at 13:11
  • 9
    `attr()` is currently only supported at the `content` property, which can be used for pseudo-elements (such as `:before`, `:after`). – Rob W Jan 07 '12 at 13:12
  • 1
    @RobW According to the MDN, the attr() function you're referring to is the one from CSS2.1, I'm referring to the CSS3 one. – Peter W. Jan 07 '12 at 20:16
  • W3C (CSS3) spec for those interested: http://dev.w3.org/csswg/css-values/#attr – colbydauph Oct 26 '13 at 02:16

5 Answers5

67

Looking at the grammar that's given in the spec:

attr( <attr-name> <type-or-unit>? [ , <fallback> ]? )

It looks like the comma between the attribute name and the unit to be used needs to be dropped:

.window > .content .wbutton.tint {
    border: solid thin attr(data-tint color);
    box-shadow: inset 0 0 50px attr(data-tint color);
}

However, even if you have the right syntax, it won't work either. It turns out, there are no known implementations of the level 3 version of attr() as of 2012...2020. To make matters worse, it's still at-risk as of the latest editor's draft of the spec.

But not all is lost: if you'd like to see this feature implemented in upcoming browsers, there is still time to suggest it in the relevant feedback channels! Here are the proposals that have been put out so far:

For the record, the basic Level 2.1 version is fully supported across recent versions of all major browsers, including IE8+ and Firefox 2+, and is used with the content property for the :before and :after pseudo-elements for generated content. The MDN browser compatibility table is applicable only to this version, and not the CSS3 version.

Hazel へいぜる
  • 2,751
  • 1
  • 12
  • 44
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • Furthermore, you *cannot* assume that a browser implements a CSS3 feature until the module has been or is being finalized in at least the CR phase. As a draft, anything can come and go. In fact, there's speculation that the `attr()` function may be dropped during the CR phase... but realistically speaking, I wouldn't bet on that happening either. Personally, I would just wait and see. – BoltClock Jan 07 '12 at 17:16
  • I'll wait for full support of CSS3 then. (Damn SO won't let me edit my previous comment) – Peter W. Jan 07 '12 at 20:24
  • 2
    Just so you know, CSS3 has reached CR now. `calc()` is now supported in every major browser apart from Opera (on Webkit browsers `-webkit-` prefixed, on the rest not), `attr()` is not yet available AFAIK. :( – mgol Sep 04 '12 at 20:30
  • 2
    @m_gol: I hope they implement it soon, otherwise it's going to bounce back to LCWD and time will be wasted. That gets annoying. – BoltClock Sep 04 '12 at 20:34
  • @m_gol `attr()` is currently supported, at least partially, in Chrome (haven't checked on other browsers yet). See http://archive.simurai.com/lab/buttons/ for an example of its use. – Marnen Laibow-Koser Oct 26 '13 at 02:07
  • 1
    @Marnen Laibow-Koser: That's CSS2.1 `attr()`, which like I said is fully supported by all browsers. We're talking about CSS3 `attr()`, which has no support beyond what CSS2.1 allows. – BoltClock Oct 26 '13 at 06:34
  • 1
    @BoltClock Oh, I see. I didn't know `attr()` even existed in CSS 2.1, but having looked at the spec again, I see that it's only the multiargument form that's new in CSS 3. Sorry for the confusion! – Marnen Laibow-Koser Oct 26 '13 at 07:05
  • @Douwe Maan: Oh hey... it's been a while. – BoltClock May 02 '14 at 06:11
  • Heh, so it has. Yo @BoltClock :) – Douwe Maan May 13 '14 at 10:09
10

As of today, the attr() in CSS3 only supports to get values from the HTML5 data attribute to set the content of an element. There is a nice fiddle whichs shows it.

I have tested it in Google Chrome 35, Mozilla Firefox 30 & Internet Explorer 11.

If you want to use HTML5 data attributes for different things in CSS3, like setting the width and the height of elements, then you need an additional JavaScript library.

Fabrice Weinberg wrote a CSS3 attr() Polyfill which handles data-width and data-height. You can find Fabrice's GitHub repository here: cssattr.js.

Benny Code
  • 51,456
  • 28
  • 233
  • 198
  • Thanks for the explanation. One consideration you may want to make in the example JS fiddle is to have a comment saying how you *don't* expect the width style to get updated, as some (like myself) may first expect to see the width take effect until reading your full answer. – mralexlau Oct 09 '14 at 20:43
  • It's not limited to HTML5 data attributes. It can be used with any attribute, whether standard or non-standard. The only limitation is its use with the CSS `content` property. – BoltClock Dec 15 '14 at 16:40
  • 1
    Please refrain from using *exact* temporal terms such as "as of today" because such are irrelevant for Stackoverflow questions. Your "today" is already years ago in the past. – vsync Jun 01 '20 at 12:37
4

I found hack. This is not attribute, but manipulate directly on styles. In Chrome Canary, you can use custom css properties, and JS for manipulate properties.

In CSS:

.some { background-position: var(--x) 0; } 

In JS:

element.style.setProperty("--x", "100px", "");
//With same success you can set attribute. 

Test case: https://jsfiddle.net/y0oer8dk/

Firefox: https://jsfiddle.net/0ysxxmj9/2/

user2454034
  • 101
  • 8
  • I like this idea as a solution, because it allows for more dynamic options. In my case I needed access the `
      ` `start` attribute for a custom counter. It's been a long day for something so simple, and this approach seems to be the more elegant in my view. Here is what I wound up doing, which would be easily adapted to any other attribute as needed... `$( document ).ready(function() { $('[start]').each(function() { this.style.setProperty('--start', this.getAttribute('start')); }) });`
    – Shane McCurdy Mar 02 '22 at 16:11
0

It does work, but not the way you think. It's not a value that's sent via a variable but more as a trigger to then assign a value to. And because of this it's better to make the data attributes something unique but simple. A small example might help:

<div class="data"><span data-width="80" data-tint="lime"></span></div>

Then in your css you would put:

.data {height: 50px; width: 100%; background-color: #eee;}
.data > span {display: block; height: 100%;}
.data > span[data-width="80"] {width: 80%;}
.data > span[data-tint="lime"] {background-color: rgba(118, 255, 3, 0.6);}

It's pointless if your doing it on a small scale but on a larger scale and with some help from SCSS some things become easier, like..

@for $i from 1 through 100 {
    &[data-width="#{$i}"] {
        .data > span {
            width: calc(#{$i} * 1%);
        }
    }
}

That will compile into CSS every percentage possibility allowing you to set your span width with data-width.

Check out the fiddle

Eugene
  • 81
  • 5
  • "It's not a value that's sent via a variable" - But that's literally what the W3C spec says it is. – Peter W. Apr 10 '18 at 19:05
  • Can you give us the link to that because I've been going by https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes and I can't find anything like that there. – Eugene Apr 11 '18 at 09:30
  • It's the first link in my question. – Peter W. Apr 11 '18 at 09:36
  • Ok. I haven't read that before and in my experience using the data attribute it that way only works in pseudo elements in content. It specifically says the color has to be either the hex value or an ident css token which I understand as the names of colors that css understands, so rgba wouldn't work and when I tried it out it doesn't work with hex or names either. – Eugene Apr 11 '18 at 11:37
  • That's the thing: The W3C says it should work like that, but not a single browser does it that way. Even now, over 6 years after I asked this question. – Peter W. Apr 11 '18 at 12:31
  • Haha, It's a crazy world we live in. But all we can do is what we can. – Eugene Apr 11 '18 at 13:55
0

What you are attempting to accomplish can't currently be achieved with data attributes as has been said by several people already. While the answer from @Eugene will work, it will add an incredible amount of bloat to your css file and is therefore unreasonable. @benny-neugebauer was correct in saying that it isn't possible with data attributes but he isn't entirely correct in saying that you need javascript to accomplish it. There is a way to achieve it with html and css only...

We need to start by converting your attribute from a data attribute to a css variable.

<a class="wbutton tint" data-tint="rgba(255,0,0,.5)" href="#">This should be red, with an opacity of 0.5</a>

becomes

<a class="wbutton tint" href="#" style="--data-tint:rgba(255,0,0,.5);">This should be red, with an opacity of .5</a>

Next, we need to modify your css slightly. It should also be noted that since you used a comma in your attr(), where you have color is where you are supposed to, or can, include a fallback in case your variable is invalid. If you wanted to declare that the attribute value should be a color then you would not use the comma.

.window > .content .wbutton.tint {
  border: solid thin attr(data-tint, color);
  box-shadow: inset 0 0 50px attr(data-tint, color);
}

becomes

.window > .content .wbutton.tint {
  border: solid thin var(--data-tint);
  box-shadow: inset 0 0 50px var(--data-tint);
}

You can see it in action below.

.window>.content .wbutton.tint {
  border: solid thin var(--data-tint);
  box-shadow: inset 0 0 50px var(--data-tint);
}
<div class="window">
  <div class="content">
    <a class="wbutton tint" href="#" style="--data-tint:rgba(255,0,0,.5);">This should be red, with an opacity of .5</a>
  </div>
</div>

Here is an article by Chris Coyier at css-tricks.com that provides more information.

Angeliss44
  • 125
  • 1
  • 3
  • 20