Elements can have multiple class names. For instance:
<div class="module accordion expand"></div>
Then in CSS, you could match that element based on any one of them:
/* All these match that */
.module { }
.accordion { }
.expand { }
You can limit your selectors to match only if several of them are present, for example:
// Will only match if element has both
.accordion.expand { }
But what about other attributes?
Class names are unique in the ability outlined above. Other attributes are not treated as “multiple values” just because they have a space in them. For instance:
<div data-type="module accordion expand"></div>
This element just has a data-type attribute with a value of “module accordion expand”, not three unique values “module”, “accordion” and “expand”. But let’s say we wanted to be able to select elements based on individual values like we can with class names.
We could do it by using a “*” substring matching attribute selector which will match if the provided string appears anywhere in the value:
[data-type*="module"] {
}
or only match when multiple of specific “values” are present:
[data-type*="accordion"][data-type*="expand"] {
}
Ever better, use the whitespace separated selector (e.g. [data-type~="expand"]
). That way you won’t get burned by something like “expand” matching “expander” when you didn’t want to.
[data-type~="accordion"][data-type~="expand"] {
}
Works in IE7+ (because IE 7 was first IE to support attribute selectors)
Cool!
Would you personally ever use this in one of your sites, Chris? I can see combining data attributes with JavaScript, but making CSS selectors for data attributes seems odd. It would have to be something generic to some extent and would be, in my point of view, easily implementable as a class. It’s also a lot more trustworthy since the compatibility for CSS classes and even multiple classes in the same selector go back way farther than the data attribute.
Knowing you, doing all sorts of over-the-edge frontier development, there might be a special reason for doing this. I just can’t read that anywhere in your article. Wanna enlighten us?
I tried to write this article three or four times. The origin of it was that I was trying to figure out what the use of the dash-separated attribute selector was, e.g. [rel|=value]. Seemed rather useless, especially since it will only match an attribute that STARTS with “value-“. That means [rel^=value] is just as useful. I literally couldn’t come up with a single use case for it.
I thought of how it might be useful to use classes like “module-a” and “module-b” on elements and be able to select them both together and separate.
But again, that’s not particularly useful. Especially since if you use multiple classes (e.g. class=”module module-a”) you’ll get deeper browser support.
Then I got thinking about classes and how unique it is that just by space separating them it’s kinda like having multiple unique values and how it’s the only attribute like that.
So then the ideas kinda melted together and thus, this article.
Would I use this in a real project? Sure. To be perfectly honest I never have but I would if it came up. A use case would be where you were using a data attribute to store some data anyway. Like let’s say geographical coordinates in a data-geo attribute. And you offered geographical search on the page. You could write a selector that would match elements based on the data-geo attribute without having to add some extra arbitrary hook to select by.
The “dash-separated attribute selector” is specifically designed for use in language attributes. The idea is to match things like en, en-US, en-GB etc.
I’ve never thought that space could affect the CSS selectors. (until html5 comes).
Chris could you also use the
[att~=val]
selector? From the spec:Yeah! That’s obviously better. Updated article.
Also, better spec to link to for the future: http://dev.w3.org/csswg/selectors4/#attribute-representation
Of course rather than using the strange spacing thing you could of course use the white-space attribute selector [att~=value].
Also supported IE7+ I believe: White-Space attribute selector fiddle
@Brendan Ha! That wasn’t there when I started typing I swear.
I’ve known about the basic technique for a long time – but never knew you could do it with things like attribute selectors!
Can really help when deciding that DreamWeaver is just not working well for JS scripts.
Class selectors are much, much faster than attributes selectors and while this is interesting I can’t think of a real-world situation where you’d prefer
data-attributes
to set style overclasses
.Got some data on that?
In your CSS example to match both class names (“
.accordion.expand { }
“) does that only affect cases where ‘accordion
‘ is directly followed by ‘expand
‘? Or is the order irrelevant?order irrelevant
Doesn’t the id attribute also support multiple white-spaced values?
Nope: http://jsfiddle.net/chriscoyier/3qgwZ/
Hmmm, guess not.
Awesome tricks! Thank you Chris, keep up the good work!
Just a caution: using [attr=val] type selectors in your css and jQuery can be pretty slow in most browsers, because there are no simple shortcuts/lookup tables/methods for them (yet). For static pages this doesn’t work out to be a huge concern, but if you intend to use these css classes dynamically (i.e. adding and removing them over time in response to user action) you can run into some real slowdowns.
We don’t often think about the efficiency of css rules, but they do start to matter in complex, dynamic pages. Using sparingly when possible.
this is realy nice thanx can we use span in place of div
May be worth mentioning that out of all the examples here, IE6 would not ignore the first one:
.accordion.expand {…}
but pick it up as being:
.expand {…}
I think something worth mentioning, too, is that attribute selection has the same specificity as classes. So using the multiple attribute method works as an excellent solution when you don’t have control over the HTML – like generated forms.