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 (.magic
). 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 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; }
Case-Insensitve Attribute Selectors
By default, the strings inside attribute selectors are case sensitive, but rather than matching multiple permutations of case in the case that you need to, you can pass a value that makes it case-insensitve:
/* Will match
<div data-state="open"></div>
<div data-state="Open"></div>
<div data-state="OPEN"></div>
<div data-state="oPeN"></div>
*/
[data-state="open" i] { }
Using Attribute in CSS
You can not only select via attributes, but use attributes in CSS content, like…
.el::before {
content: attr(data-prefix) ": ";
}
Hopefully someday we’ll get support for types and fallback in the attr()
function in CSS, like:
.el {
/* <div class="el" data-font-size="18"> */
font-size: attr(data-font-size px);
/* <div class="el"> */
font-size: attr(data-font-size px, 18px);
}
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.
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.
That would be that a lot of people still use old browsers…
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)…
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!
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!
In that case you would just use the cascade and change the style back for links that start with http://yourdomain.com
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; }
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!
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.
“If the line/selector style is in red, it works.”
Red usually indicates it doesn’t work I suggest changing it to green instead ;)
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.
Really nice round up – thanks
Amazing post Chris… i knew this better way now and gonna use it from my next project …. Thanks for sharing !
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.
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?
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.
Dont forget, target=”_blank” isn’t valid XHTML. I believe it is still valid for transitional HTML, tho I could be wrong.
<a href=”#” rel=”nofollow”>External</a>
try again….. [ onclick = ” this.target=’_blank’ ” ]
Thanks for that little snippet. I don’t use it often but now use it and validate.
WOW! That’s cool! CSS never ceases to amaze me with it’s pure diversity.
Thanks Chris.
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.
Nice! A nice real world example for rel$ is to add icons to links, for example a pdf icon on every link ending with .pdf.
Thanks!
det var bra!!! Like it, like it..
Oh yeah! For sure, that’s an awesome use. Example for peeps:
a[href$=pdf] {
background-image: { url(/images/pdf-icon.png) no-repeat; }
padding-left: 30px;
}
Hey Chris, a typo in the code above ;)
background: url(/images/pdf-icon.png) no-repeat;
I couldn’t get it to work in Firefox unless I changed ‘background-image’ to just ‘background’:
a[href$=pdf] {
background: url(../img/pdf.png) no-repeat;
padding: 0 0 0 24px;
}
I’m guessing that’s because you can’t put the ‘no-repeat’ in a background-image property. Pretty sure Chris meant to put background, being that he included the no-repeat.
Hey Chris! Awesome post! I had no idea CSS was so versatile.
And it’s also encouraging to see that even friggin’ genius get going to fast and type weird code :)
Keep it comin’, man – I check your site everyday!
Nice job!
Remember to be nice with links to pdf’s (100%).
<a href="docuemnt.pdf#zoom=100" rel="nofollow">
Have both selectors.a[href$=".pdf"], a[href$=".pdf#zoom=100"] { /<em>Your lovely styles here</em>/ }
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.
Hey, how about using http://code.google.com/p/ie7-js/ ? Ofcourse, it could slow down everything, but it’s the price ie6 user will pay :) And i think this time it’s not something like rounded corners, which you can ommit, it’s usability at sake, and we should provide it even to those ignorant IE users :))
And as i have read http://www.evotech.net/blog/2007/05/ie7-css-selectors-how-they-fail/ , it states that there are some problems with selectors in ie7, so i think you should point that out too.
Thanks a lot! Didin’t even knwo about these pseudo-regular expressions in sellectors.
Definitely some powerful stuff here. I really like this because of the fact that wordpress supports the whole rel thing for the blogroll, etc.
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!=https://css-tricks.com] instead.
Well, you can always use jQuery for that. But as author stated, there’s rel=”external” for that in wordpress.
You can just set the attribute style for a link that begins with http:
a[href^=http://] { background: url(extIcon.gif); }
…then correct the style for links inside your domain:
a[href^=https://css-tricks.com] { background: url(none); }
Another thing to note about attribute selectors – they’ve got less specificity than regular class or id selectors, so:
a[id=someID] {color: blue; } will be overridden by a#someID { color: red; }
You can use a[href^=http://]:not([href^=http://yourdomain.com]), but it has no support with any IE version.
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.
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.
Ahhhhh…now I understand! I’ve been using Bluetrip and H5, without fully grasping what was going on between the []s.
Thanks again, Chris!
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(/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).
CSS Attribute selectors are great and use them everyday, though i didnt know about the “in dashed” and “in space delimited” variations. Thanks for the tips.
However, you missed on something extremely important. IE7 can be crashed with a specific selector. Yup you heard me right. Just place the following CSS either in your page or style sheet and it will take down IE7 without even logging a windows event regarding the crash.
button[value=””]
or
button[value=”some value”]
Deliciously nuts and bolts geeky, not to mention very useful. This is why I love this site.
Here’s the kind of code I use:
a:not([href^="http://www.arpia.be"]):not([href^="#"]):not([href^="/"]):after {
content:"\279F";
}
This adds a little arrow after every external link.
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.
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.
woops,
<a href="#" class="external" target="_blank"
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.
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.
Those are all very interest uses of selectors. It sure makes developing websites easier with those in mind.
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!
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.
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.
Wow! I can’t believe that I’ve never heard about this before.
Awesome stuff!
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(/images/icon_pdf.gif) top right no-repeat; }
But that’s been said multiple times. That’ll teach me to read the other comments before commenting. Haha.
wow! Advanced CSS stuff! nice
That was really helpful. Thanks a bunch!
To validate as valid CSS you need to make sure it’s element[attr=”value”], note the quotes.
Also I forgot to mention that a lot of these aren’t supported in IE, as they’re a part of CSS3. See http://www.css3.info/preview/attribute-selectors/
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.
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!
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.
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?
Great read. Much appreciated!
Thank you… never know about that stuff…
See also here:
http://ipinfo.info/netrenderer/index.php?url=http://www.css3.info/preview/attribute-selectors/%23begins
They do work in Internet Explorer 7 and higher
how do you find this stuff out
Yet another valid reason to forget IE6 ever existed…
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!
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.
Thank You Chris ! Just learnd something new.
Very useful indeed. Thanks a lot for the tips.
Hey this means you can also style image differently according to their type!
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.
This is so WIN! Thanks for writing this Chris. :)
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]
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.
Fantastic, thank you very much! Cheers from Sao Paulo, Brazil.
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/
wow, this seems to be a really helpful little bastard. Thanks for sharing it!
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.
If only our users would STOP using IE6. They still account for at least a quarter of our revenue.
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.
Agree with Skilldrick… Great article. Thanks for the reminder and kick in the backside.
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)
[edit]
3. webdevs shouldn’t give a rats …
[/edit]
I’m currently using
time[datetime*="01T"]
throughtime[datetime*="31T"]
to set thebackground-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!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?
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
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!
Very useful post. This would solve lot of my problems and I am sure we can reduce CSS size.
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)
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…
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!
Really really helpful, especially with the auto generated class in wordpress (tag-link-1,tag-link-2,tag-link-7 .. ). Awesome. Thanks a lot!
Brilliant post Chris! It’s always nice to learn something new at the start of my week!
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.
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 :-)
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 }
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.
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:
For example, you want to pick all elements with
data-kermit
you could…And so on and so forth…
You are doing Great Work Sir you are our expert trainer i used your tricks many time
you are also my inspiration sir
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.
Ooof, that is to say: