CSS3 Attribute Selectors Query

10 Sep

The other day I was working on an internal UX Guidelines website and instituting one of the very things that I was advocating when I ran into a problem. Essentially, I was implementing the code to create a file type icon at the end of links so that all PDFs would show a PDF icon, all SWFs would have a Flash icon and all external links would have an external link icon, using the CSS3 attribute selectors.

a[href$='.E'] – finds all a elements that end with a particular string, such as .pdf or .swf
a[href^='http'] – finds all a elements that start with a particular string, in this case ‘http’ (internal links are relative, so they don’t include the full URI

The result looks something like this (links won’t work):

This is an example of a link to a PDF DOCUMENT.

This is an example of a link to a FLASH APP.

This is an example of an internal link.

This is an example of an external link.

The CSS behind it was also pretty simple:


a[href$='.pdf'] { display:inline-block; 
	padding-right:20px; 
	line-height:18px;
	background:transparent url(adobereader_icon.png) center right no-repeat; 
	}
a[href$='.swf'] { display:inline-block; 
	padding-right:20px; 
	line-height:18px;
	background:transparent url(adobe_flash_icon.png) center right no-repeat; 
	}
a[href^='http'] { display:inline-block; 
	padding-right:20px; 
	line-height:18px;
	background:transparent url(ext_link_icon.png) center right no-repeat; 
	}

The problem came when I wanted to identify an external link that was also a PDF. I needed to come up with something that would identify both pieces in the URI and put in a combo icon. There is a precedent to do this using the same attribute selectors:
p[class*='blue green'] selects all links with a class of BOTH “blue” and “green”, but not if they only have one or the other.

But this wasn’t working with the href when I tried all of these (and many more):
a[href*='http pdf']
a[href*='http' 'pdf']
a[href*='http'+'pdf']

A solution

Finally, I stumbled upon a solution that uses the new :not selector. This selector allows you to select elements which – obviously – do not match the attribute/string selected. So, I came up with a pattern that basically says give all PDFs the PDF icon but NOT if the element also includes the http at the start of the URL. Together, the code looked like this:

a[href$='.pdf']:not([href^='http']) { display:inline-block; 
	padding-right:20px; 
	line-height:18px;
	background:transparent url(images/icons/page_white_acrobat.png) center right no-repeat; 
	}
a[href^='http'] { display:inline-block; 
	padding-right:20px; 
	line-height:18px;
	background:transparent url(images/icons/ext_link_icon.png) center right no-repeat; 
	}

And the final result looked like this:

This is an example of a link to a PDF DOCUMENT.

This is an example of a link to a FLASH APP.

This is an example of an internal link.

This is an example of an external link.

This is an example of an external PDF document.

Success!

Caveats

One strange thing that I noticed is that this only works when the CSS is in a particular order (I’m assuming based on precedence). The :not attribute has to be at the top; the general PDF code at the bottom. When I had the order (top to bottom): External PDF > PDF > SWF > external link, it didn’t work. Once I changed it to External PDF > SWF > external link > PDF, it did. Kind of odd, but I’ll deal with it.

Tags:

Leave a Reply