Grow your CSS skills. Land your dream job.

The Skinny on CSS Attribute Selectors

Published by Chris Coyier

CSS has the ability to target HTML elements based on any one of their attributes. You probably already know about classes and IDs. Check out this bit of HTML:

<h2 id="title" class="magic" rel="friend">David Walsh</h2>

This single element has three attributes: ID, class, and rel. To select the element in CSS, you could use an ID selector (#first-title) or a class selector (.magical). But did you know you can select it based on that rel attribute as well? That is what is known as an attribute selector:

h2[rel="friend"] {
   /* woohoo! */
}

There is a lot more to attribute selectors though, so let's look closer at all the different options and try to cover some "real world" scenarios on when they might be useful.

Attribute Exactly Equals Certain Value

In the example we used above, the attribute of the h2 element was "friend". The CSS selector we wrote targeted that h2 element because it's rel attribute was exactly "friend". In other words, that equals sign means just just what you think it does... an exact match. See another basic example:

<h1 rel="external">Attribute Equals</h1>
h1[rel="external"] { color: red; }

A great real world example of this is styling a blogroll. Let's say you had a list of links to friends sites like this:

<a href="http://perishablepress.com">Jeff Starr</a>
<a href="http://davidwalsh.name">David Walsh</a>
<a href="http://accidentalninja.net/">Richard Felix</a>

Then you wanted to style each link slightly differently. The traditional way would probably be to give each link a class name in which to target, but that requires additional markup which is always a nice thing to avoid (semantics and all). Another way might be to use :nth-child, but that requires their order to never change. This is the perfect use for attribute selectors... the links already have a unique attribute in which to target!

a[href="http://perishablepress.com"] { color: red; }

I believe the most common use of regular attribute selectors is on inputs. There are text, button, checkbox, file, hidden, image, password, radio, reset, and submit (did I miss any?). All of them are <input>'s, and all of them are very different. So doing something like input { padding: 10px; } is a bad idea most of the time. It's very common to see things like:

input[type="text"] { padding: 3px; }
input[type="radio"] { float: left; }

It's really the only way to get your hands on certain types of inputs without screwing up the others and without adding extra markup.

Note on Quotes: You can usually get away without using quotes in attribute selectors, like [type=radio], but the rules for omitting quotes are weird and inconsistent across actual browser implementations. So, best practice, just use quotes, like [type="radio"]. It's safer and always works.

Attribute Contains Certain Value Somewhere

This is where it starts getting more interesting. The equals sign in attribute selectors may be prefaced by other characters which alter the meaning a bit. For example, "*=" means "match the following value anywhere in the attribute value." Look at this example:

<h1 rel="xxxexternalxxx">Attribute Contains</h1>
h1[rel*="external"] { color: red; }

Remember that classes and ID's are attributes too, and can be used used with attribute selectors. So let's say you were writing CSS for a site where you couldn't control the markup and a sloppy developer had three DIVs you need to target:

<div id="post_1"></div>
<div id="post_two"></div>
<div id="third_post"></div>

You could select them all with:

div[id*="post"]  { color: red; }

Attribute Begins with Certain Value

<h1 rel="external-link yep">Attribute Begins</h1>
h1[rel^="external"] { color: red; }

A real world example of using this would be, say, that you wanted to style every single link to your friends site different than other links. Doesn't matter if you are linking to their homepage or any subpage, any links to them you want to style up.

a[href^="http://perishablepress.com"] { color: red; }

That will match a link to their homepage, but also any other subpages as well.

Attribute Ends with Certain Value

We can select based on how attribute values begin, why not end?

<h1 rel="friend external">Attribute Ends</h1>
h1[rel$="external"] { color: red; }

A good use case for these is labeling file download anchor links with icons based on what type of file they are. For example, PDF's get a PDF icon and Word Documents get a Word icon:

a[href$=".pdf"] { background: url(icon-pdf.png) left center no-repeat; padding-left: 30px; }
a[href$=".doc"] { background: url(icon-doc.png) left center no-repeat; padding-left: 30px; }

Attribute is within Space Separated List

You probably already knew that you could apply multiple classes to elements right? Well if you do that, you can still use .class-name in CSS to target any one of them. Attribute selectors aren't that easy. If your rel attribute has multiple values (e.g. values in a space separated list) you'll need to use "~=":

<h1 rel="friend external sandwich">Attribute Space Separated</h1>
h1[rel~="external"] { color: red; }

You might be thinking, why would I use this when *= would also match this and be more versatile? Indeed it is more versatile, but it can be too versatile. This selector requires the spaces around the value where as *= would not. So if you had two elements one with rel=home friend-link and one with rel=home friend link you are going to need the space-separated selector to target the second one properly.

Attribute is the start of a Dash Separated List

This will select if the start of a dash-separated list of attribute values matches the selector.

<h1 rel="friend-external-sandwich">Attribute Dash Separated</h1>
h1[rel|="friend"] { color: red; }

Note that even though it matches based on the start of the selector, the entire first part of the string before the first dash needs to match. So in the above example, if the rel attribute was friend2-external-sandwich, it would not be a match while the ^= attribute selector would have.

Multiple Attribute Matches

Vital to note is that you can use multiple attribute selectors in the same selector, which requires all of them to match for the selector itself to match.

<h1 rel="handsome" title="Important note">Multiple Attributes</h1>
h1[rel="handsome"][title^="Important"] { color: red; }

Browser Support

Every single example above works in all modern browsers: Safari, Chrome, Firefox, Opera, and IE. Internet Explorer has perfect support for all of these down to version 7, but zero support in 6. To test in your browser, see the test page. If the line/selector style is in red, it works.

Comments

  1. James
    Permalink to comment#

    Awesome Chris – I never knew that. I will definitely be using this method more in future! Strange, I’ve never seen a website use this form of code in style sheets either. Maybe it isn’t as well known as we expect.

    • sigex
      Permalink to comment#

      That would be that a lot of people still use old browsers…

  2. Leonardo
    Permalink to comment#

    OK, now this is creepy.
    At this moment I’m re-reading Eric Meyer’s book on CSS and I just covered the part on attribute selectors (page 38)…

  3. Permalink to comment#

    Oooft, nice, there are tones of applications for this.

    a[href^=http://] { color: red; }

    Quickly target all external links using CSS. Love it! Also, saw your name on the front cover of .net today and nearly feinted… I would have bought it (it’s a great zine), but didn’t have time as I was at the train station.

    As always, keep up the great work!

    • Permalink to comment#

      Could be some issues with sites that use WordPress and themes that reference all internal links using the domain, so the rel=”external” would have to be used in that case..

      But I agree, for most situations it’s great!

    • Eddy
      Permalink to comment#

      In that case you would just use the cascade and change the style back for links that start with http://yourdomain.com

    • Eddy
      Permalink to comment#

      That is:

      a {color: blue; }
      a[href^=http://] { color: red; }
      a[href^=http://mydomain] { color: blue; }

    • Or you can use :not() and eliminate the extra selector:

      a {color: blue; }
      a:not([href^=http://mydomain]) { color: red; }

    • Tim
      Permalink to comment#

      Thanks so much for this article, it’s proved to be a massive timesaver!

      I’ve used these tips to create a stylesheet targeting <a> tag attributes, that I now apply to large webpages I’m marking up. The CSS applies different background colours to links depending on a huge number of conditions, e.g.

      No ‘title’ attribute
      Absolute internal links
      404s
      Non-HTML links e.g. PDFs
      Fragment links

      This means when I’m checking these massive web documents against the plain Word document the client originally sent, it’s immediately apparent which <a> tags require attention AND what needs to be done. You can use the same technique to target any HTML element.

      Thanks so much!

  4. Permalink to comment#

    You don’t see it because of the lack of support for older browsers.

    You can achieve the same results using classes for each element. I would personally prefer this route for forms if it was possible but classes will probably remain the defacto choice.

  5. V1
    Permalink to comment#

    “If the line/selector style is in red, it works.”

    Red usually indicates it doesn’t work I suggest changing it to green instead ;)

  6. Michael
    Permalink to comment#

    Wow. that’s all I got to say. Makes me wonder what kind of cool, little known tricks will be in css3 when it’s done.

  7. Permalink to comment#

    Really nice round up – thanks

  8. Amazing post Chris… i knew this better way now and gonna use it from my next project …. Thanks for sharing !

  9. Andy Jones
    Permalink to comment#

    For links to exteral sites, you could also target the ‘target’!

    So if you have a link to an external site, you will probably be opening that in a new window.

    so…

    a[target=_blank] { color: red; }

    What do you reckon Chris?
    Works for me!

    Andy

    • Nothing wrong with that. It’s just links to external sites don’t necessary have that, that’s only when you intend the link to open in a new window/tab.

    • Andy Jones
      Permalink to comment#

      true – but I think 9 times out of 10 my clients want external links to open in a new tab/window. (rightly or wrongly!)

    • Hope you read this Chris, but I’ve been hardcoding the target attribute in all my links. I really don’t see a problem with this, and won’t get into the whole debate, but should I start using rel=”external” and such?

    • Permalink to comment#

      I think most usability engineers agree on the fact that no link should ever launch a new window, because that makes a choice that really is up to the user and more importantly because it breaks the back button.

      Then again, if your client demands it and expects it…

    • True, BUT in moments where you simply cannot open something in the same page, for example when you’re filling out a form and want to view the terms, you have to make it open in a new page.

      What I don’t understand is how rel=”external” any improvement over target=”_blank” other than the fact that it validates in strict?

    • “…BUT in moments where you simply cannot open something in the same page, for example when you’re filling out a form and want to view the terms, you have to make it open in a new page.”

      Not necessarily. There ARE options that would allow a user to view the terms without launching a new page, such as modal boxes / windows.

    • Garrett Baldwin
      Permalink to comment#

      Dont forget, target=”_blank” isn’t valid XHTML. I believe it is still valid for transitional HTML, tho I could be wrong.

    • Chris
      Permalink to comment#

      <a href=”#” rel=”nofollow”>External</a>

    • Chris
      Permalink to comment#

      try again….. [ onclick = " this.target='_blank' " ]

    • ckn
      Permalink to comment#

      Thanks for that little snippet. I don’t use it often but now use it and validate.

  10. Brussells
    Permalink to comment#

    WOW! That’s cool! CSS never ceases to amaze me with it’s pure diversity.
    Thanks Chris.

  11. I knew about this, but not all the little things in between with the | and ~.

    Also since I am sure this works in all browsers (too bad for IE6 eh?) I can start to use this more.

  12. Thanks, Chris, for another application of regex. CSS becomes more dynamic every time I look. These examples will come in handy. My only nitpick: “There is a lot more too attribute selectors” uses the wrong homophone.

  13. Michal Kozak
    Permalink to comment#

    Thanks a lot! Didin’t even knwo about these pseudo-regular expressions in sellectors.

  14. Permalink to comment#

    Definitely some powerful stuff here. I really like this because of the fact that wordpress supports the whole rel thing for the blogroll, etc.

  15. Permalink to comment#

    It would be nice if you could use != for ‘not equal’. Since WordPress uses the http: for all links you can’t use a[href^=http://] to target external links. However it would be nice if you could do something like: a[href!=http://css-tricks.com] instead.

    • Permalink to comment#

      Well, you can always use jQuery for that. But as author stated, there’s rel=”external” for that in wordpress.

    • You can use a[href^=http://]:not([href^=http://yourdomain.com]), but it has no support with any IE version.

  16. I picked up the book “Advanced CSS” last week and they talk about a lot of these advanced selectors we don’t know (or think about) It’s amazing how powerful some of these selectors are, yet most of them aren’t used very often anywhere.

  17. Great explanation of the different CSS attribute selectors. These are not something that I have used in the past out of shear ignorance of when or how to use them. This is a huge help and I see that I will be making use of this much more in the future.

  18. Ahhhhh…now I understand! I’ve been using Bluetrip and H5, without fully grasping what was going on between the []s.

    Thanks again, Chris!

  19. Permalink to comment#

    I’ve never thought of doing things this way, never even crossed my mind to fall away from using classes etc. Is it cross browser friendly? There seem to be some people saying yes some no! Would be interesting to run some browser testers on all the different variations.

    Really like the idea of using it for the file extension purpose:

    “a[href$=pdf] {
    background-image { url(http://cdn.css-tricks.com/images/pdf-icon.png) no-repeat }
    padding-left: 30px;
    }”

    Nice article!

    • It’s not working for me in internet explorer 7. I’m working on a site where we’re have lots of logos displayed for informational purposes. One of the logo owners want’s theirs taken down until we get licensing. So instead of re-writing back end code, I tried this to remove the logo for this case only.

      div.foo .bar[style*=xyz] {
      background-image:none !important;
      }

      Does not remove the background image in IE7. I have to use !important because it’s an inline style that adds the background (I know that’s not separating content from style, but worked better this way for programming).

  20. Permalink to comment#

    Deliciously nuts and bolts geeky, not to mention very useful. This is why I love this site.

  21. Permalink to comment#

    Fully agree that using rel is better than introducing a new class, however I do have to nitpick a little.

    In the real world, most of the time you are not saving any markup. In my experience, almost no links have the rel atttibute in place. So by not using classes and switching to rel you are only switching one attribute for another. Conceptually much better, but there is no real saving IMHO.

    • James
      Permalink to comment#

      By introducing the rel attribute you are killing two birds with one stone. You can remove the target (assuming you are using rel=”external”) and you are styling external links, which is much more efficient than having <href=”#” rel=”nofollow”>. Again, preventing yourself from introducing a new class and allowing yourself to remove the target attribute.

    • James
      Permalink to comment#

      woops, <a href="#" class="external" target="_blank"

    • Brian
      Permalink to comment#

      What I think he was getting at was not just for links but for anything like H1 or img tags as well. Instead of using class=”” you are only basically switching it for rel=”” in which case doing it purely to reduce markup is redundant. However using this to select specific tags based on their attributes is what Chris was hinting at. Especially good for forms IMO. instead of giving each tag it’s own class to target it you can do it by input[type=text/submit/button] etc. Which is where it comes in handy.

    • Permalink to comment#

      You don’t have to target rel, you can do it with any attribute. For instance, i’m using

      input[type="submit"]

      as a selector in one of my stylesheets.

  22. Those are all very interest uses of selectors. It sure makes developing websites easier with those in mind.

  23. Very helpful article. I barely knew about them, but would never use them while coding! Now I will be sure to do so, especially since I’ll not be supporting IE6 anymore.

    Thanks!

  24. Permalink to comment#

    Good, this is helpful. I’ve been trying to get links to take styles from their container, like

    #main a:hover {color:red}

    but have been finding it either doesn’t work or doesn’t stay restricted to the container; i.e. the above example turns all links on the page to red. Is that supposed to work?

    Either way, I should probably try attribute selectors instead.

    • Permalink to comment#

      a:link and a:visited must be in the stylesheet above a:hover or it won’t work. I had this issue for a while on some sites, until i found out about it.

  25. Permalink to comment#

    Wow! I can’t believe that I’ve never heard about this before.

    Awesome stuff!

  26. For “Attribute Ends with Certain Value,” I often find myself using that to style certain links based on their filetype.
    a[href$=pdf] { padding-right:16px; background: url(http://cdn.css-tricks.com/images/icon_pdf.gif) top right no-repeat; }

  27. wow! Advanced CSS stuff! nice

  28. Permalink to comment#

    That was really helpful. Thanks a bunch!

  29. To validate as valid CSS you need to make sure it’s element[attr="value"], note the quotes.

  30. Nice summary, Chris.

    I sometimes intentionally use an attribute selector for a class or ID I want to hide an element from IE6.

    For example:


    div[class="whatever"] {
    background-color: red;
    background-image: url(semi-transparent-background.png);
    }

    This sometimes saves me having to create an IE6 stylesheet just to override one element.

  31. Permalink to comment#

    This might be the wrong spot to ask this but I felt like it wasnt to off topic.

    I am having a problem in IE8

    This css will not work:

    input:active[type=image] {position:relative;top:1px;left:1px;}

    or

    input:focus[type=image] {position:relative;top:1px;left:1px;}

    Any help is greatly appreciated!

    • Gringer
      Permalink to comment#

      Two possible ansers, not sure myself:

      1) :active and :focus should be at the end of the selector (ie. input[type=images]:active ) and therefor is failing.

      But since you said it’s only failing for IE8, :

      2)
      :hover and :active only work in IE for anchor-elements () and are therefor failing on input elements.

  32. Permalink to comment#

    Wow! Awesome stuff! This is definitely something not usually covered in many websites!

    How does the use of attribute selectors reflect on the page load time? Is it the same as ‘normal’ use of CSS or is there extra processing involved?

  33. Jack
    Permalink to comment#

    Great read. Much appreciated!

  34. Permalink to comment#

    Thank you… never know about that stuff…

  35. Gringer
    Permalink to comment#
  36. Permalink to comment#

    how do you find this stuff out

  37. EvilDr
    Permalink to comment#

    Yet another valid reason to forget IE6 ever existed…

  38. A perfect real world example of ‘h1[rel$=external]‘ (matching the end), is one I just did after reading your post. I used it to style pdf download links with a pdf icon: a[href$=pdf]. Works an absolute treat. Cheers!

  39. Really good stuff. I am also guessing this would be really helpful for jQuery selectors.

    Does anyone know in which browsers do not support it?

    Useful as usual Chris.

  40. Permalink to comment#

    Thank You Chris ! Just learnd something new.

  41. Permalink to comment#

    Very useful indeed. Thanks a lot for the tips.

  42. Permalink to comment#

    Hey this means you can also style image differently according to their type!

  43. Meatian
    Permalink to comment#

    I knew about this, but examples shown above are something strange to me: I understand that only link and a elements can take rel attribute.

  44. This is so WIN! Thanks for writing this Chris. :)

  45. jiewmeng
    Permalink to comment#

    i found out that the dash separated selector does not work. it seems to work in your test page because its actually using the “contains” selector [rel*=external]

  46. Permalink to comment#

    h1[rel|=external] { color: red; }

    Attribute Dash Separated

    This is not work correctly like you told in Firefox v3.6 and Chrome v5 because it only red when only i swap external to the front like this

    Attribute Dash Separated

    In your example you can try by remove css rel*=external from you css code and see the result.

  47. Permalink to comment#

    Fantastic, thank you very much! Cheers from Sao Paulo, Brazil.

  48. Permalink to comment#

    Nice work Chris. Btw if you want to see which browsers support these selectors you can visit either:

    http://www.findmebyip.com/#css3-selectors

    or

    http://www.css3.info/selectors-test/

  49. Permalink to comment#

    wow, this seems to be a really helpful little bastard. Thanks for sharing it!

  50. Permalink to comment#

    I will have to keep this in mind for future projects. It seems like an interesting way to get even more specific with my CSS which is always fun.

  51. Amber
    Permalink to comment#

    If only our users would STOP using IE6. They still account for at least a quarter of our revenue.

  52. Permalink to comment#

    I’d been aware of these for a while, but they were one of those CSS things that I generally ignored as not being cross-browser enough. But I see it’s only IE6 now that doesn’t support them, which I’m starting to ignore now, so I’m going to have to start playing about! Thanks for the kick up the backside.

  53. bobby
    Permalink to comment#

    Agree with Skilldrick… Great article. Thanks for the reminder and kick in the backside.

  54. Permalink to comment#

    I’ve been using this for some time, but only in JQuery because the lack of support in IE6 … yes, I hate ie(6) as much as the rest of you, but I do want everybody to see the same website …

    Hey Chris,
    I don’t know you already had this poll, maybe this would be a good one:

    Webdevelopers should make there websites …
    1. the same for every browser (mobiles excluded)
    2. degrade nicefully on older browsers
    3. webdevs should give a rats ass for browsers that aren’t even supported anymore by there own developers (like IE6)

  55. I’m currently using time[datetime*="01T"] through time[datetime*="31T"] to set the background-position of a calendar icons sprite for each post listed in the David Chambers Design archives. I love using attribute selectors to keep my markup free of unnecessary class names!

  56. That is great, I knew that but honestly never paid that much attention to and or never did more research about it but i wonder can we use them because most of the users are still using damn IE6?

  57. Permalink to comment#

    The Rel$=external could be very useful for recognizing file types. For example, if you have links to PDF’s and normal webpages, you could place icons in front of the links to show that it is a web page or a pdf, because you will know the link ends on .pdf or not.
    Quite a useful example in the real world I guess

  58. Permalink to comment#

    Wow, i never thought that all modern browsers supports that Selectors! Would save many dispensable class names – and an IE6 Stylesheet, to :P

    Greetings from Germany!

  59. Sai
    Permalink to comment#

    Very useful post. This would solve lot of my problems and I am sure we can reduce CSS size.

  60. Emanuele
    Permalink to comment#

    Hi all,
    question:
    it si possible to add more than one “rel” to a link? if yes is this affecting SEO?

    example:

    (a href=”www.something.com” rel=”nofollow” rel=”site”)this is a link (/a)

  61. Permalink to comment#

    I had a basic knowledge of attribute selectors, but I didn’t know that it was that extensive. This was very informative and will definitely come in handy in the future…

  62. I didn’t know anything about this. This is awesome, especially for input. I’ve been making .text and .button classes for my input, extremely annoying. This makes much more sense, thank you very much!

  63. luca
    Permalink to comment#

    Really really helpful, especially with the auto generated class in wordpress (tag-link-1,tag-link-2,tag-link-7 .. ). Awesome. Thanks a lot!

  64. Brilliant post Chris! It’s always nice to learn something new at the start of my week!

  65. Sean
    Permalink to comment#

    Actually, I just though of using this to automatically put some margin around images that I am aligning right or left.

    For example:

    <img align="right" src="whatever.jpg" />

    And then using CSS attribute selector:

    img[align=right] { margin-left:10px; }

    This gets me over what has always given me heartburn: users floating pictures using align, but not adding the appropriate class to ensure margin is added.

  66. Excellent post, i searched alot for an example of

    a:not([href ^=http://my.domain.com]) !
    Knew something more elegant existed, and finally found the answer, and alot more here :-)

  67. Gabe
    Permalink to comment#

    All right!
    Now I was able to remove the embedded youtube videos from being printed on my @media print styles

    iframe[src*="youtube"] { display: none }

  68. Permalink to comment#

    Thanks for posting this Chris. Does anyone know how expensive the part class selector (class*=”span”, used in bootstrap for grids) is?

    • I wouldn’t spend too much time thinking about the expensiveness of selectors. It only barely matters in the most extreme of circumstances.

  69. Jason
    Permalink to comment#

    There’s an additional way of using attribute selectors which is missing here. You can select element(s) which simply have an attribute present, using:

    [my-attribute-name] {
         /* I'm stylin' */
    }
    

    For example, you want to pick all elements with data-kermit you could…

    [data-kermit] {
        background-color: green; /* it ain't easy being green */
    }
    

    And so on and so forth…

  70. Prashant Gola
    Permalink to comment#

    You are doing Great Work Sir you are our expert trainer i used your tricks many time

  71. Eric

    When you use an attribute selector to look for properties inside a style attribute and you are supporting IE8, you’ll need to provide two selectors:

    div[style=FONT-SIZE],
    div[style
    =font-size]

    Why?? When IE8 parses the page, it converts all property names inside style attributes to UPPERCASE.

    • Eric

      Ooof, that is to say:

          div[style*=FONT-SIZE],
          div[style*=font-size]
      
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".