Rethinking Links: The Search for a Better HREF

Alex Hall

Links have always been, well, links. A blue bit of text on a web page that takes you somewhere else. What’s perhaps most surprising about links is how little they’ve changed since their inception in 1965.

This is most likely because they haven’t needed to. They are just a way to navigate between two places.

However, in this age of fantastic new web technologies and platforms, links have changed too. In 2014 they can point to anything you want them to point out — external or internal pages, PDFs or SVGs, images or archives, even trigger events in JavaScript.

The problem is, looking at a (most commonly) blue piece of text gives absolutely no indication of what it’s likely to do! Sure, you can use helpful title attributes and informative link text, but at the end of the day, this might not be how your link needs to be visible.

So, how can we make links more informative?

Auticons are a great CSS implementation

Auticons are a great CSS implementation

One great implementation I’ve seen recently (courtesy of Christian Heilmann) is Heydon Pickering’s Auticons.

Heydon uses CSS3 selectors to visually change the appearance of links without requiring any extra markup — and this works really well.

But, if you have a page full of links there is a problem: you end up with a cluttered page, crammed full of icons, as well as the blue link text!

The same applies to Mark Boulton’s Sparkicons — though that article is a very interesting read.


Positioning the icon above the link.

Positioning the icon above the link.

On To Some Code

My original idea involved using the rel attribute on the link to determine our styles as, in CSS3 you can use attribute selectors with ease.

Note that I’ve used *= for the selector, because the attribute might have more than one value (demo):

HTML

<a href="http://google.com" rel="external" title="An External Link">To Google</a>

CSS

a[rel*='external'] {
    position: relative;
}
a[rel*='external']:after {
    content: " \f08e";
    font-family: "FontAwesome";
    font-size: 12px;
    left: 50%;
    margin-left: -6px;
    opacity: 0;
    position: absolute;
    top: -22px;
    -webkit-transition: all .25s linear;
       -moz-transition: all .25s linear;
        -ms-transition: all .25s linear;
         -o-transition: all .25s linear;
            transition: all .25s linear;
}
a[rel*='external']:hover:after {
    opacity: 1;
    top: -18px;
}

My first example makes the icon fade in (using Font Awesome) above the link when you hover over it.

This is a really quick and dirty way to show that the link has some functionality beyond just taking you somewhere. You know it’s going to lead you off the website and can then act accordingly.


Animated demo

The icon glides into view when the users interacts with the link

Bringing the Icons Inline

However, for links in the flow of text, you might not want the icon to appear from the top.

I’ve played around with a few ways of doing this.

So far, the best way I’ve found that doesn’t cause content to jump around when responding to the hover, involves setting aside some negative space for the icon.

Here’s the code:

a[href^='http'] {
    padding-right: 15px;
    position: relative;
}
a[href^='http']:after {
    content: "\f08e";
    font-family: "FontAwesome";
    font-size: 12px;
    right: -15px;
    opacity: 0;
    position: absolute;

    -webkit-transition: all .25s linear;
       -moz-transition: all .25s linear;
        -ms-transition: all .25s linear;
         -o-transition: all .25s linear;
            transition: all .25s linear;
}
a[href^='http']:hover:after {
    opacity: 1;
    right: 0;
}

As you can see in the demo, we reserve some white space to the right of the link that is filled with the icon during the hover state. I don’t think this causes much of a display problem, especially once you realise that space does actually have some content in the hover state of the link.

But it’s not perfect.

Another alternative without the space reservation would be to have the icon appear on top of the text. For that you could give the icon a background color and change the opacity down a little, as in this example.

Personally, I do like this implementation but not the fact that you then can’t read the text in the link once hovered.


Text Out, Icon In

One final method was to hide the text completely and replace it with the icon. I think is a lot cleaner than having the icon appear on top of the text. Here is an example of this.

I’ve also added a bit of extra flair, and changed the icon as you lose the hover. Obviously, this is not helpful or informative, but just demonstrates some extra things you can do with this.

The only caveat for this example is that the link needs a fixed height for the line-height to work properly. I did manage to create a version that doesn’t, but this requires an extra piece of markup in the link to function correctly.

I do prefer this animation though, so if you don’t mind an extra span try it out (please note: on some versions of Chrome the transition property in CSS3 is buggy when the content property is changed. I’ve filed a bug report and this should be fixed in upcoming versions).


What About Mobile?

This is the big question mark: None of this will work correctly for mobile because there is no “hover” state. You see the link as it is, there’s no way to see the hover state until you actually touch the link to follow it.

This makes all of the above pretty redundant for mobile users, which is where it is almost certainly more relevant. You’re less likely to want to click on a PDF, for example, if you’re on a mobile device.

So, how can we get around this?

Well, what if we use media queries to always show the icons when the viewport is below a preset width?

@media only screen and (max-width: 800px) {

    a[href^='http']:after,
    a[href^='https']:after{
        opacity: 1;
        right: 0;
    }

}

(Resize your browser window in this demo to see the icon appear permanently below a certain threshold)

Another approach would be to use JavaScript to intercept the first touch on the link, and show the prescribed icon instead.

You already see this approach in some JavaScript tooltips implementations. On mobile they will show the tooltip on the first tap, and then follow the active link on the second tap.

However, I wouldn’t expect this to be a popular method, as having to click twice just to follow a link will irritate a lot of people.


Accessibility

There are some accessibility issues with this too. These are covered pretty well here by Karl Groves. The tl;dr is that content added by a CSS property is invisible to screen readers, so none of this information really helps those browsing the web with a screen reader.

However, you’d hope the title attribute of the link does enough to describe what its purpose (Plus, I believe the href attribute of links is read out on screen readers.)

Also, for people who like to browse with the keyboard, the examples above wouldn’t show a change when the link is active. To rectify this, you would just need to add a[href^='http://']:focus wherever you have the hover styles.

An easy fix.


And Finally…

As with Auticons, you can make deploy this approach widely throughout your project. If you have a lot of links to different content types, you can use the $= selector in CSS3 to target different links with certain files types.

For instance, if you want to just add an icon to PDF documents you might use the following as your selector:

a[href$='.pdf']

Add an icon for PDFs to your CSS and you’ve given people a handy little hint as to what they’re clicking on! Feel free to post your thoughts in the comments below.

And remember, you don’t have to use a font for your icons. You could create yourself custom images or use an icon-set with a background-image in the CSS.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://stephenmorley.org/ Stephen Morley

    The Text Out, Icon In variant is slightly buggy: the version without the extra span cuts off descenders, while the version with the extra span can sometimes flicker between the two states if the mouse is positioned near the top (something which can be fixed by slightly adjusting the offsets used in the hover state).

    • Alex Hall

      Yeah, I found that the method with the span worked great in Firefox but Chrome had issues where the content property of the CSS was changed between states. Good spot with the adjustments though!

  • Stuart Laverick

    Each of the options has advantages and disadvantages. Which to use I think comes down to context. If the link is to a large file such as a heavy PDF, then some type of warning would be appropriate for mobile or other bandwidth sensitive users. Equally if the PDF is poorly accessible then this may be information that would be of value to screen reader or assistive technology users. This would lend itself to having permanently accessible information associated with the link, perhaps in the link title.
    For desktop / tablet users where they have few accessibility requirements and plenty of bandwidth, it becomes more of a usability enhancement exercise. The issue here may be to draw attention to the potential of the link, for example if it is to a media item, or social media activity. In this case the decision would be whether the user should be informed at the point of action (i.e. on hover) or as they scan the page. Promotional links may want a constantly visible icon, while others would be suitable for one of the CSS transition techniques you described.

  • http://www.facebook.com/helen.robertson.1420354 Helen Robertson

    Was having a play with your example (v. nice), added a bounce and rotate and got a rather ‘cute’ effect.

    a[rel*='external']:after { content: ” 21ea”; font-family: “DejaVu Sans”; font-size: 1.5rem; left: 30%; opacity: 0; position: absolute; top: -1rem; transition: all .4s cubic-bezier(0.5, -1, 0.2, 1.8); }
    a[rel*='external']:hover:after { -webkit-transform: rotate(90deg); opacity: 1; top: -1rem; left: 70%; color: #ff6a00; }

    Cheers!

    • Alex Walker

      Have you got it as a JSfiddle example, Helen?

      • OphelieLechat

        @disqus_unskvztVN5:disqus was one step ahead of you, @disqus_DWdNL0UToz:disqus! :)

  • Mats Svensson

    Some really bad examples here.
    Or good ones, for causing bad usability in the name of unnecessary bling.

    How do i highlight the text in the link, if i want to copy it, if you HIDE it when i get near it with the pointer?

    And why should i have to mouse over every single link on the page to find out witch ones are external?

    • http://www.facebook.com/helen.robertson.1420354 Helen Robertson

      Well written links should indicate by their context where they’re going, but (I agree these examples aren’t refined), they do give additional information to the user. Accessibility and Usability are complex subjects and this article demonstrates an another tool for the thoughtful designer.

    • Alex Hall

      Like I say, this may not be appropriate for you or your target audience, but does highlight some of the things you can do with CSS to help “present” links more informatively. The JavaScript method might be considered better because it injects content into the page, but then most screen readers still wouldn’t be able to get any extra context from that.

      Surely you’d only be interacting with a link if you were planning on using it? Otherwise it wouldn’t matter whether you knew it was external or not.

  • http://www.facebook.com/helen.robertson.1420354 Helen Robertson

    PS. Sorry. This is pedantic but I’ve noticed a tiny little Semantic prob:

    In the first example you have a[rel*='external'] but only the header “link” attribute should use the value ‘external’.

    • Alex Hall

      Hmm… interesting point about semantics. I have always used rel=”external” to indicate that a link will be heading off site no matter where the link is. As I recall it was used this way specifically for those bots looking through your site to indicate that the link took them off domain.

  • http://garyjones.co.uk/ Gary Jones

    If you just want to highlight external links, then use of the :not() selector comes in handy e.g.:

    a:not([href*="sitepoint"]):after {
    content: ’261E’;
    }

  • Peter Adams

    Three problems I see:

    First, while the sliding icon in the white
    space after the link is cool, it interrupts the flow when you are
    reading the text. Call me an old fuddyduddy, but I think the most
    important thing about a block of text is how easy it is to read. The
    extra white space is a small problem that becomes larger if there is
    punctuation involved.

    Second, overriding the default tooltip
    (e.g. the link address) with a custom one (e.g. “To Google”) is a big
    security no-no. We in the field constantly harp on users to hover over a
    link to make sure it is going where they think it’s going. This defeats
    the purpose.

    Finally, while the idea of an off-site icon or a
    file type icon is a nice touch, it should never be the only way of
    presenting the information, a primary tenet of 508 accessibility. A
    simple piece of text like “(55KB PDF)” is never a bad idea.

  • Sp4cecat

    There’s a really high risk here of having your links mistaken for clever advertising. The whole paradigm of how links work is now locked in firmly, like a floppy disc icon for the ‘save’ option.