Attach icons to anything with CSS

Filed: Sun, Jan 07 2007 under Programming|| Tags: css1 selectors icons css

Conditional CSS selectors work only with modern browsers (FireFox 2.0+, Opera 9, and IE7). Of particular note, the techniques described in this article will work with IE7 only if you supply a document type. Your page doesn't necessarily have to validate, it just needs a document type to get IE out of quirksmode. Browsers which can't do conditional selectors simply won't display the icon. -- This note was added after publication.

Thanks to CSS selectors it's possible to attach icons to anything you want just by adding an attribute of your choosing to your HTML. Want a popup icon? try <a href='#' icon='popup'> how about a magnifier? <a href='#' icon='mag'>. You can even add them automatically for file types. Here's how.

A few days ago, while using stumble-upon, I stumbled on a site which showed how to conditionally append icons to the end of hypertext links using css. What made the article interesting was that it used CSS conditionally. For instance...

a[href $='.pdf'] { 
   padding-right: 18px;
   background: transparent url(icon_pdf.gif) no-repeat center right;
}

This would attach a pdf icon to the right of any hyperlink who's URL ended in '.pdf' like this. This was pretty exciting and heady stuff. It meant I could show the file type visually with that application's icon just by including a few lines in my master css file. I didn't have to worry about it at all in my html, css would add the icon for me automatically.

This trick makes use of what the official specifications call "attribute selectors". For instance in our above example we have our anchor tag which says to style this element for anchors and then, defined by brackets, [href $='.pdf'], we see if the anchor has an href attribute and if it does if that attributes value ends in '.pdf'.

This works with any attribute. For instance...

span[id ^='google'] { 
   background-color: green;
}

Any span which has an id which starts with 'google' will be assigned a green background.

The kicker is that the attributes can be made up. That is you can create your own attributes. For instance, as I integrated askthecssguy's icons into my site I found his solution to work extremely well with mail and document types (pdf, word, excel, etc.), but because the ability to match and exclude substrings was so limited it didn't work very well for automatically detecting internal and external links.

I worked around this by creating my own attribute called icon and then matched it in css like this.

a[icon ^="out"] {
   padding-right: 20px;
   background: transparent url(http://www.hunlock.com/images/external.gif) no-repeat center right;
}

This looked for an attribute called icon and if the value began with "out" it would show a little external icon beside the link like this. All by adding icon="out" to my tag like this...

<A HREF="someurl.com" icon="out">

Now that was pretty cool because it meant that I could define a visual icon to show beside my links just by adding my own attribute to my anchor, I could also add other icons as they became needed like popups or a magnifier. And the neat thing is that I could use them or not, as I wanted.

The epiphany came when I realized I could do the selection without needing a tag. What that means is that...

[icon ^="out"] {
   padding-right: 20px;
   background: transparent url(http://www.hunlock.com/images/external.gif) no-repeat center right;
}

now worked with ANY tag which had icon="out" as an attribute, be it <A icon="out"> or <span icon="out">.

Now the conditional elements of the selectors are limited (which is the reason I had to opt for custom attributes), but they are powerful. The biggest obstacle is you can only match true, not false -- that is you can only look for what's there, not what's not. Here's an overview of the conditional syntax.

[foo]        -- Has an attribute named "foo"
[foo="bar"]  -- Has an attribute named "foo" with a value of "bar" ("bar")
[foo~="bar"] -- Value has the word "bar" in it somewhere ("blue bar stools")
[foo^="bar"] -- Value begins with "bar" ("barstool")
[foo$="bar"] -- Value ends with "bar" ("I was at the bar")
[foo*="bar"] -- Value has bar somewhere ("I was looking for barstools")     

With these simple selectors you can attach any style you want to any object either automatically (as in the case of checking for a file extension in a HREF attribute) or manually (by creating your own attributes). You can have more than one attribute selector as well. For instance [foo^="foo"][foo$="bar"] { background-color: blue } would style anything that had an attribute with a value which begins with foo and ends in bar.

And as an added bonus here are a few icon libraries (all free and wonderful) to get you started:


Addendum

This addendum was posted after this article was published.

If you're concerned with having your page validate by the validation services you can either use an XHTML doctype and define your custom attributes, you can use the REL attribute, or you can use dual classnames in your class definitions as such:

<A HREF="#" class="somestyle out">

This applies both .somestyle and .out to the anchor and it has the added bonus of being liked by the validation services. So with this you get a validator friendly way to have my global icons and still apply whatever other styles you want to the object.

Happy coding!