NB: This page is archived without styles. Go to our home page or read our blog.

A tribute to selectors

I wanted to learn more about CSS attribute selectors.

Two things happened on Friday which prompted me to talk about CSS attribute selectors. The first was an email plopping into my inbox,


Hi Andy, I was just scanning through your CSS and noticed the following line of code:

div[id="content-sub"] p span { 
display : block; 
background : url(../images/x.png) no-repeat; }

Im basically wondering what the [ ] are for? I've never seen it used anywhere and couldn’t find any information about it on Google. Thanks, Alex.


The second was working on a new web site with the mighty Brothercake. Scanning through the CSS he had written, like Alex, I was intrigued by,

*[id^="content-supp"]#content-supp:lang(en) {
left : 34.6%; 
margin-left : 0; }

So, wanting to find out about these types of selectors I did a bit of reading around, but many of the explanations were a tad complicated. So I made some experiments of my own and thought I’d share them.

Before we start, if you’re reading this with Internet Explorer 6, go and amuse yourself for a few minutes, as attribute selectors won’t work in that browser. Still here? Phew, let’s crack on.

Attribute selectors

Attribute selectors allow you to target an element based upon its 'attribute'. Here are some examples, (attributes in bold).

<a href="" title="" ></a> 
<q cite="" ></q> 
<img src="" alt="" /> 
<div id="" ></div > 
<p class="" ></p>

The first example targets any element which has a specific attribute, for example all anchors which have a title attribute. In this example, anchors with titles attributes will display a dotted bottom border. (1)

<a href="/" title="Andy Clarke" >Malarkey</a> 
a[title]  { border-bottom : 1px dotted #900 }

(2) Now for greater specivity, we can also target only anchors where the title attribute contains only the word ‘Malarkey:’

<a href="/" title="Malarkey" >Malarkey</a>
a[title="Malarkey"]  { border-bottom : 1px dotted #900; }

(3) instances where ‘Malarkey’ comes at the beginning of the attribute,

<a href="/" title="Malarkey is Andy Clarke" >Malarkey</a> 
a[title^="Malarkey"]  { border-bottom : 1px dotted #900; }

(4) instances where ‘Malarkey’ comes at the end of the attribute,

<a href="/" title="Andy Clarke is Malarkey" >Malarkey</a>
a[title$="Malarkey"]  { border-bottom : 1px dotted #900; }

(5) or even titles which contain the word ‘Malarkey’ somewhere in the attribute.

<a href="/" title="Wot a handsome chap Malarkey is" >Malarkey</a> 
a[title*="Malarkey"] { border-bottom : 1px dotted #900; }

Moving on

Of course, these selectors are not limited to anchors, they may be used for any element with an attribute and the possibilities seem almost endless. Perhaps,

I thought I’d have a bit of geeky fun by playing with <blockquote> and ‘cite’ (apologies to those concerned ;)) Your thoughts?


Replies

  1. #1 On February 20, 2005 07:51 PM Rob McMichael said:

    There is some great stuff here.

    One practical use I could see, would be to:

    a[href$="https://"

    and then perhaps style all external links differently to internal ones :) Lots of possibilities though, roll on IE7 and Longhorn, or a virus that can replace IE with a slightly better browser.

  2. #2 On February 20, 2005 08:01 PM Pierce said:

    The notation is a bit similar to grep.

    Something for the future maybe. Since IE isn’t supporting it, I can’t see it being used for anything crucial at the moment? People are generally already using classes and ids to achieve the possible uses you’ve cited, although this could simplify CMSs, ie, users not having to add classes or categories to articles, and letting the selectors take care of things based on content. I'd be interested to see some working practical applications.

  3. #3 On February 20, 2005 08:36 PM Jeena Paradies said:

    Thanks for this article, I was looking for a easy description of this attribute selectors. I found it the first time in this A List Apart article about print stylesheets: https://www.alistapart.com/articles/goingtoprint/ and thought that we should really start to use such things.

    #content a[href^="/"]:after {
      content: " (https://www.alistapart.com" attr(href) ") "; }

  4. #4 On February 20, 2005 08:42 PM Jeff Croft said:

    Attribute selectors are sweet. Too bad they don’t work in IE. Because of that, right now I usually just use them for little ‘rewards’ that visitors using modern browsers get. I don’t think its safe to rely on them just yet.

  5. #5 On February 20, 2005 08:46 PM Rob Mientjes said:

    One really practical usage of the attribute selectors is probably using PNG files for advanced browsers only, so you’d have:

    div#container {
    background: url(/images/container.jpg) repeat-y 50% 0;
    }

    And for the cool people you’d have:

    body[id="container"] {
    background-image: url(/images/container.png);
    }

    To name just one of the cool uses.

  6. #6 On February 20, 2005 09:42 PM harry Jones said:

    Makes it very easy to do icons next to links depending on their file type, e.g.

    a[href$=".pdf"] {
    background: url(pdf_icon.gif) no-repeat;
    }

    a[href$=".doc"] {
    background: url(word_icon.gif) no-repeat;
    }

    I guess this is just another item of the list of "things we could do if IE didn't exist"

  7. #7 On February 20, 2005 09:45 PM Justin Perkins said:

    I like it, first time I saw this was last month at Andy Budd’s site, first comment posted. I think it’s going to be great if that other browser lets us use it.

  8. #8 On February 20, 2005 10:25 PM Steve Webster said:

    It’s also useful for adding “this link opens in a new window” indicator icons to links:

    a[target="_blank"] {
    background: url(newwin_icon.gif) no-repeat;
    }

    Like others have commented here I don’t use these fancy selectors for anything crucial to the site, just little rewards for people with decent modern browsers.

  9. #9 On February 20, 2005 10:37 PM jordan said:

    Ah, very informative and useful. Since I know that FireFox supports these, I’ll have to see if I can use it with a FireFox skin (my current project).

  10. #10 On February 20, 2005 11:03 PM Richard M. said:

    I think the beautiful thing about selectors is that browsers DON’T support them as well as they should. Which gives us a great set of hacks to filter CSS. This is from Brothercake, posted at Coding Forums.

    /* opera 7 and 8 */
    .foobar
    { properties }

    /* safari/konqueror and mozilla */
    *[class^="foobar"]
    { properties }

    /* mozilla, but not safari/konqueror */
    *[class^="foobar"]:lang(en)
    { properties }

    /* ie */
    * html .foobar
    { properties }

    /* windows/ie5 */
    @media screen, projection
    {
    * html .foobar
    { properties }
    }

  11. #11 On February 20, 2005 11:35 PM Malarkey said:

    Thanks for the comments so far guys. Interesting points...

    @ Pierce:
    Since IE isn't supporting it, I can’t see it being used for anything crucial at the moment?

    Interestingly, I am currently making some assumptions and decisions during the coding of the new Karova site… I have decided so far that;

    Better browsers get specially designated external links,

    a[href^="https://"] {
    padding-right : 9px;
    background : url(external.gif) no-repeat right center;
    text-decoration : none;
    }

    Although the layout will work in all browsers, most of the design touches will only work in better browsers. I am also using attribute selectors to format much of the content and pseudo classes to give better browsers nice, rounded boxes whilst IE gets square boxes.

    .keypoint:before {
    background : transparent url(right.gif) no-repeat top right;
    content : url(left.gif);
    }

    If IE7 catches up, then cool. If not, IE gets a perfectly serviceable, if slightly reduced design. It all depends on your audience.

  12. #12 On February 20, 2005 11:59 PM Jon said:

    Attribute selectors are also quite useful for stripping out ads via a user-defined style sheet.

  13. #13 On February 21, 2005 12:11 AM Jeff Minard said:

    I think that this is MOST useful for links and for form styling.

    input[type=radio]

    etc. Good work around the classing every form element redundantly.

  14. #14 On February 21, 2005 12:31 AM Mike said:

    I’m very impressed with how clear your explanation is and how much more understanding I got from it. Thank you so much for keeping it simple for us simpletons ;-) I love real world examples.

  15. #15 On February 21, 2005 01:00 AM Alex said:

    Thanks for the really clear explanation.
    Like Jeff said this would really useful for formatting forms. It’s a shame IE doesn’t support it.

  16. #16 On February 21, 2005 01:02 AM Chris Lienert said:

    Post par excellence! I knew very little about attribute selectors but now I can see them appearing in my code before long :) Fingers crossed that there’s some form of support in IE7 although by the time it’s released Firefox may rule the world.

  17. #17 On February 21, 2005 05:07 AM Michael Newton said:

    Note that only examples 2 and 3 above are part of CSS 2. The others are part of CSS 3, which is currently only a candidate recommendation. It's unlikely that they won't be included in the final document, but it is something people should be aware of.

    https://w3.org/TR/CSS21/selector.html#attribute-selectors There are a number of very cool selectors that will hopefully show up in Gecko browsers one day. Here’s the bug with all the selectors that are being considered.

  18. #18 On February 21, 2005 07:45 AM Med said:

    Great suggestions! My favourite is missing though:

    h3~* {padding:0 4px;}

    This works in all latest Mozilla browsers. What it does is that every element after the h3, within the div the h3 element is in, get styled with a 4px padding on it’s left and right side. A lot better then styling each possible elements that comes after it. In my case sometimes is would be a paragraph, sometimes a list and sometimes a table. And i still have my options open if i for instance want to insert a blockquote after it.

  19. #19 On February 21, 2005 09:37 AM Richard@Home said:

    Excellent post Mr. Malarkey. You've produced exactly what’s missing from the majority of documentation on the subject: Simple Examples! Bravo.

    Richard M: I’ve been avoiding selectors because of their lack of support in IE. Relying on this lack of support for hacks is going to come back and haunt you once they do get supported.

    Most of the examples here could be achieved with a few simple Javascript presentational scripts and, if done correctly, should be future proof too. Hmm. Sounds like a good subject for another article…

  20. #20 On February 21, 2005 10:25 AM Anthony said:

    A brilliant tip, thank you very much!

    As everyone has already said it’s a shame about the lack of IE support but you come to expect such things! Anyway within 10 mins of reading this I’ve got it up a running on our sites staging server ready for upload (www.chester.gov.uk). External links and new windows are an ever changing issue with gov sites. So we’ve got blue dashed lines for external links as they should be this week and green dashes for ones that haven’t been changed yet (ones with popups using target _blank).

    So quite useful for us—if not for all of the IE using masses that visit our site.

  21. #21 On February 21, 2005 10:50 AM Reuben Whitehouse said:

    Cracking! I’d also come across [ ]'s somewhere but couldn’t find an understandable explanation, until now :o)

  22. #22 On February 21, 2005 12:29 PM Brothercake said:

    Allrighty—how about this—it’s actually not real, I’ve just made it up, but wouldn't it be useful :)

    a[href%="^(https://)?([-_\.a-zA-Z0-9]+)$"]:after {
        content:" (" $2 ")";
    }

  23. #23 On February 21, 2005 12:47 PM Keith said:

    The syntax looks a lot like XPath, which would make sense seeing as we’re dealing with XHTML.

  24. #24 On February 21, 2005 01:15 PM Lars said:

    My compliments on a great article, Mr. Clarke. If used with subtlety and elegance, I believe attribute selectors can do more than just enhance the user experience of modern browsers as they can help win over IE users.

    But what is the * character in your last example?

  25. #25 On February 21, 2005 01:23 PM Richard@Home said:

    Here’s a quick demo to illustrate using ‘Javascript selectors’ which I knocked up during a slow lunch hour:

    Javascript Selectors Demo

    The code is overly verbose to keep things readable, but you get the idea

  26. #26 On February 21, 2005 01:38 PM Robert Wellock said:

    The universal selector, written "*" matches any element; if that answers the question, e.g. anywhere the string Malarkey appeared in the anchor title attribute a little like a wildcard.

  27. #27 On February 21, 2005 02:47 PM Jonathan Snook said:

    Richars@Home: for those looking for an IE compatible approach, look no further than Dean Edward’s IE7 (soon to be renamed IE8, I suspect)

  28. #28 On February 21, 2005 03:18 PM Richard@Home said:

    Dean:

    I looked into IE7 (only briefly, I never looked at the code) a while back—its a fantastic job and should be applauded. I should have mentioned it in my post. However, it’s a bit of an overhead if you just want one or two of its vast feature set. I really only wanted to illustrate how simple the technique was.

  29. #29 On February 21, 2005 03:57 PM Max Khokhlov said:

    Thanks for the info. I’m sure there’s plenty of uses for the hack. Let’s just hope, IE becomes a browser that’s more or less appropriate for its primary function—browsing.

  30. #30 On February 21, 2005 08:16 PM Rachel said:

    Thanks for this article. It’s really easy to understand. I was just thinking the other day how useful it would be if something like this existed and here it is! I think I’m going to be using this quite a bit from now on!!

  31. #31 On February 21, 2005 10:34 PM Stephen Lewis said:

    Just the explanation I was looking for, thank you. I was aware of the attribute selector, but for some reason had never really considered using it. This article changed all that, and a few hours after reading it I’ve already put it to good use. Excellent.

  32. #32 On February 22, 2005 01:08 AM Paul Moment said:

    You’re all in luck. It just so happens that an enterprising coder decided to use javascript to bring IE into complete CSS compatibility. Check out the final product—which he calls IE7—at https://dean.edwards.name/IE7/compatibility/. From what I can tell, the code enables full support for CSS2 and CSS3 selectors. Have fun! :)

  33. #33 On February 22, 2005 02:17 PM Tim Hettler said:

    One instance in which i have found selectors really useful is to target text input tags. Often times I’ll create custom borders but don’t want them applied to, say, submit buttons. Of course, I’ll only use selectors in experimental sites until IE catches up :-P

  34. #34 On February 22, 2005 05:40 PM Doug said:

    Am I missing something here? I can have links present in as many different ways as I want using css instead of creating a selector class.

  35. #35 On February 22, 2005 06:36 PM Malarkey said:

    @ Doug: Here's a nut-shell, as an example,

    Normally, to style external links differently from internal ones, we could add class="external" to external anchors, then with a wee bit of CSS, ( a.external {Rules go here} ), style them as required. The advantage of this method is that modern(ish) browsers get the same styling. (I used this method on malarkey.co.uk.

    Some (including me) might balk at adding further mark-up to a document to achieve a purely visual effect when this type of stuff is properly left purely to CSS. That is why attribute selectors are so cool. Of course the problem is a lack of support by IE and that is why many (including some commenters here) don't use them widely.

    I don’t actually agree. All cars can run on high-octane fuel, but most don’t get the advantages. Using high-octane won't hurt the car and using attribute wisely won't harm IE (the Lada of all browsers).

    Look out for the release of my new Karova design in a few weeks. I have taken CSS2 and CSS3 selectors, pseudo-classes, 32bit PNGs etc. to the limit as our target audience will largely be using modern browsers. For Opera users (who don’t enjoy CSS3), the design is slightly cut-down, IE6 users get a more cut down version and IE5 and IE5.5 users get (XXXXXX Ed: deleted!)

    OK, let’s leave that surprise for another day. (And if your name is Budd, Santa Maria or Marcotte, don't go spoiling the surprise ;) )

  36. #36 On February 22, 2005 08:22 PM dotjay said:

    Patrick has a good use for attribute selectors in his link styling using MIME types experiment. Still not sure of the usefulness of a selector like div[id="such-and-such"] over div#such-and-such though. Am I missing something?

  37. #37 On February 22, 2005 09:34 PM Mark Priestap said:

    Excellent article. Hopefully IE will get its act together. This could be tremendously powerful.

  38. #38 On February 22, 2005 09:58 PM Carlos Porto said:

    My brain was a bit hazy understanding selectors, but Its all clear now. Looks like I won’t need glasses after all. Thank you for writing this excellent article.

  39. #39 On February 24, 2005 05:51 PM Peter said:

    Indeed a great article. I wonder when Bill figures out how he can make his people perform the same trick the open source guys have been doing for a while now!

  40. #40 On February 25, 2005 01:40 AM Joel Goldstick said:

    I’m baffled. Nice idea, and it seems that lots of people have checked out the example. However, It doesn’t work on my Firefox or Opera (8) browsers (windows 2k). Seems there is a problem with the html related to pre inside blockquote or vice versa.

    All the same, I’m glad I found your site

  41. #41 On February 28, 2005 10:13 AM Phil Baines said:

    a[href%="^(https://)?([-_\.a-zA-Z0-9]+)$"]:after { content:" (" $2 ")"; }

  42. #42 On February 28, 2005 10:15 AM Phil Baines said:

    Right, I am 99% sure that only the code was in the blockquote when I submitted that comment above. Doh!

  43. #43 On March 1, 2005 12:50 AM NeefRoel said:

    Some additional uses:
    Show the language of the targeted document:
    [hreflang]:before { content: '[' attr(hreflang) ':]' }
    Show the accesskey of an anchor:
    [accesskey]:after { content: '[' attr(accesskey) ']' }
    Show the XFN-relationship of the linked person:
    a[rel]:after { content: '(' attr(rel) ')' }
    Show the title of an item on focus
    [title]:focus:after { content: ' ' attr(title) }
    Reveal insertions and show update-time:
    ins[datetime]:before { content: 'Update ' attr(datetime) ': ' }
    Show alternative text as a description of an image:
    img[alt]:after { content: attr(alt) }
    Show the citation source of a blockquote:
    blockquote[cite]:after { content: close-quote ' - ' attr(cite) }

  44. #44 On March 1, 2005 01:32 AM Malarkey said:

    @ NeefRoel: Wow! There is some clever stuff rattling around in your brain! :D

  45. #45 On March 1, 2005 05:01 PM brothercake said:

    @Phil Baines - yes exactly :) it should match a URL and print it without the https:// as a pseudo-element or it would, had I not missed a "/" from the character class :o But nothing supports it because I made it up; something I’m considering submitting to the w3c

  46. #46 On March 1, 2005 09:07 PM Aankhen said:

    Richard@Home: You might want to take a look at cssQuery: https://dean.edwards.name/my/cssQuery.js.html

    brothercake: I would second that proposal.

  47. #47 On March 3, 2005 12:40 PM David Bloomfield said:

    Would something like this work for the lowsrc attribute of an img tag?

    In an img tag put lowsrc="thumb" and then in the css put
    img[lowsrc="thumb"] { background-image: url(../images/imageloading.gif); }

    I’m trying to get this to work but I’m not having any luck. Is this possible?