Identifying External Links With CSS

As you may have noticed, recently I started identifying external links on this website with a little arrow symbol: ⇗. Most people agree that this is a neat idea – little visual cue that tells you the link points to an outside resource. It distinguishes the links to interesting articles from references to my older and less sophisticated rants from the past. I’m doing this via really simple CSS trick which I actually stole from underscorebleach.net:

a[href^="http"]:after {
	color: gray;
	content: "\21D7";
	font-size: 1.2em;
}
 
a[href^="http://terminally-incoherent.com"]:after,
a[href^="http://www.terminally-incoherent.com"]:after {
	content: "";
}

Simple regexp like pattern matching. First rule applies the style to all absolute links (ones that start with ‘http’) while the second one clears it of the more specific links which point back to this website. Any relative links will remain un-styled. Simple isn’t it?

Unfortunately I’m running into an ugly problem with this. If you look at the sidebar for example, you will notice that some of the small button links also have the little arrow applied to them. I’m not really happy with this behavior but I can’t figure out how to prevent it from happening. Of course I could simply put these buttons in a div, and use an overriding CSS rule to disable the formating there but that’s not the point. I just don’t want to apply this style to any image links. My initial instinct was to simply do:

a img:after {
	content: "";
}

Unfortunately that doesn’t work. Can you tell me why? It doesn’t work because the content style is applied to the A element while the above selects the IMG element. In CSS you always drill down the DOM tree – each time you specify a child element, the style gets applied to that child. Ideally, you would want to have some sort of a parent selector – something like:

a < img { /* stuff */ }

This would mean select element A whose child is an element IMG. But no dice. This is not the way things work. People have been asking for this feature since the beginning of time and it is unlikely that it will ever get implemented. I can sort of see why too – it would just be messy forcing the rendering engine to reverse up the tree and re-cascade all the styles below. Obviously this is not the way to go.

I wish there was a way to select a text only node, since this is precisely what I need here. I want to put the little arrow on all text links, and ignore all image links. So having a text-only selector would be perfect. I’m not the only one who thought about it either. Alastair Campbell for example proposes the following syntax:

a[href^="http"]:text-only { /* stuff */ }

I can totally get behind that notation, and I don’t really see huge problems with implementation. Unfortunately, no one at W3C seems to be considering this. It is a problem that is constantly resurfacing. I believe that every time someone decides to identify external links with CSS (which is probably quite often) they bump into this problem and realize that there is no way to solve it in css.

There are workarounds of course. You could for example define a custom class for image links and then make sure you use it every time you actually put one on your page. Something like:

<a href="http://example.com" class="imglink">
	<img src="/img/foo.png"></a>

Then you just define a.foo to have blank content and you are home free. Unfortunately if you are like me and you have a website full of image links, you probably won’t want to go back and change all of them to use that particular class. In fact, while you are doing this, you might as well just quit using that regexp solution I posted above and simply start marking your external links as class=’external’ instead and avoid this whole issue all together.

Slightly more elegant solution would be to use JavaScript. If you are using JQuery for example you could just use the :has selector:

$("a:has(img)")

But, do I really want to run a tight loop checking all the links on every single of my pages? It is a performance hit, and yet another script that needs to run before your page is ready for consumption. I’d rather avoid this sort of thing if I can.

So what is your solution? Do you have a clever trick to get around these issues? Do you make your external links with CSS but do not run into the image problem? Let me know. I’d love to see if this can be done properly. :)

This entry was posted in programming and tagged , . Bookmark the permalink.



6 Responses to Identifying External Links With CSS

  1. aaaaaaaaa UNITED STATES Konqueror Ubuntu Linux says:

    from reddit

    Why not just stick rel=”external” on the links and use a[rel="external"] ? No “hacking” necessary.

    furthermore, when your CMS processes submitted text, you could remove the rel from links that contain images. still semantically incorrect, i know, but it’s better than messing with classes.

    Reply  |  Quote
  2. Luke Maciak UNITED STATES Mozilla Firefox Ubuntu Linux Terminalist says:

    That would probably be an optimal solution, but keep in mind I have an archive consisting of approximately 5 years of daily posts. I could start putting the rel on external links today but it would not work retroactively without running some regexps on the whole archive.

    I would also need to pre-process the incoming links in the comments to make sure the external ones are appropriately tagged. All in all, not a perfect solution. If I was starting a new blog today, I’d probably consider going that route.

    Reply  |  Quote
  3. Jam UNITED KINGDOM Mozilla Firefox SuSE Linux says:

    This is fantastic :)
    I’m going to have to use it on my blog.. if you don’t mind that is ?

    And can’t just have something like:

    <a href="...." / rel="nofollow">

    and then have the code for the external link innbetween CSS tags that name it extlink?

    Sorry if that is confusing, or just plain dumb :)

    Jam

    Reply  |  Quote
  4. Luke Maciak UNITED STATES Mozilla Firefox Windows Terminalist says:

    @Jam: No problem – that’s why I post things here – so that people can use it if they want. :)

    As for you question – I’m not sure what you mean, but I think the answer is probably yes. Do you mean something like:

    <a href="...."  class="extlink" rel="nofollow">

    or

    <a href="...."  rel="nofollow extlink"  rel="nofollow">

    If yes then you could totally do that. It won’t affect any of your old links that don’t have the class extlink.

    Reply  |  Quote
  5. Instead of using a character and the :after pseudo-element, I use the icon solution from http://www.psyked.co.uk/css/auto-matic-link-icons.htm.
    At first I was having the same issue with images, but one thing I tried is something like this:

    #content a[href^="http:"] {display:inline-block;padding-right:14px;background:transparent url(/images/external.png) center right no-repeat;}
    #content a[href^="http:"] img {margin-right:-21px;padding-right:7px;}

    The image still has a link indicator, but it’s hidden underneath the image itself. This works primarily because all images in my content are padded uniformly (at 7px, not 6 or 8, don’t make fun of me).
    Hope this helps.

    Reply  |  Quote
  6. Luke Maciak UNITED STATES Mozilla Firefox Ubuntu Linux Terminalist says:

    [quote post="2673"]he image still has a link indicator, but it’s hidden underneath the image itself. This works primarily because all images in my content are padded uniformly (at 7px, not 6 or 8, don’t make fun of me).[/quote]

    Well, 7 is a perfectly respectable number. :)

    I may switch to image based link indicators at some point just to hide them on image links. :P

    Reply  |  Quote

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>