Grow your CSS skills. Land your dream job.

Multiple Attribute Values

Published by Chris Coyier

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"] {

}

View Demo

Works in IE7+ (because IE 7 was first IE to support attribute selectors)

Comments

  1. Julian Cizmic
    Permalink to comment#

    Cool!

  2. 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.

      [class|=module] { /* shared characteristics */ }
      .module-a { /* unique characteristics */ }
      .module-b { /* unique characteristics */ }

      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.

    • Scott Vivian
      Permalink to comment#

      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.

  3. Permalink to comment#

    I’ve never thought that space could affect the CSS selectors. (until html5 comes).

  4. Permalink to comment#

    Chris could you also use the [att~=val] selector? From the spec:

    Represents an element with the att attribute whose value is a white space-separated list of words, one of which is exactly “val”. If “val” contains white space, it will never represent anything (since the words are separated by spaces). If “val” is the empty string, it will never represent anything either.

  5. BigAB
    Permalink to comment#

    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

    • BigAB
      Permalink to comment#

      @Brendan Ha! That wasn’t there when I started typing I swear.

  6. Permalink to comment#

    I’ve known about the basic technique for a long time – but never knew you could do it with things like attribute selectors!

  7. Permalink to comment#

    Can really help when deciding that DreamWeaver is just not working well for JS scripts.

  8. 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 over classes.

  9. 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?

  10. cnwtx
    Permalink to comment#

    Doesn’t the id attribute also support multiple white-spaced values?

  11. Permalink to comment#

    Awesome tricks! Thank you Chris, keep up the good work!

  12. Drew
    Permalink to comment#

    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.

  13. Bacha
    Permalink to comment#

    this is realy nice thanx can we use span in place of div

  14. 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 {…}

  15. Permalink to comment#

    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.

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".