Web Design
Links and Buttons
Introduction
The long standing convention for Web links is that they are blue and underlined. Visited links are purple. For many, that's sufficient (and for some usability and accessibility advocates, it's essential). However, most designers don't like following conventions; they prefer to have the freedom to design. While I have nothing against spicing up links in general, one must be cautious; form should follow function. A pretty link is useless if the desired user can not identify it as a link.
This exercise offers some ways CSS can be used to customize links, ranging from simply changing their color, to the creation of fancy buttons.
Changing link colors
The easiest way to change the look of a link is by using pseudo-classes. There are five pseudo-classes that can be used in conjunction with the <a> (anchor) tag: link, visited, hover, active, and focus. Link is the general, inactive, unvisited state of a link. Visited refers to a link to a page that the user has been to recently. Hover is triggered when the user places her mouse over the link. Active occurs when the link is clicked. Focus indicates which link is currently active when scrolling through several links with keyboard commands.
Start by creating some links to play with:
<p><a href="#">A Dummy link</a></p> <p><a href="http://www.google.com">Google</a></p> <!-- we'll use the links below for techniques described in sections further down the page --> <p><a href="fakeFile.pdf">Another Fake link</a></p> <p><a href="#" class="fancy">Fancy link</a></p> <p><a href="#" class="basicButton">Sample Button</a></p> <p><a href="#" class="graphicButon">Graphic Button</a></p> <p class="slidingDoor"><a href="#">Sliding Door</a></p> <p class="slidingDoor"><a href="#">Much Wider Sliding Door</a></p>
<p class="slidingDoor"><a href="#">Thin </a></p>
To alter a link color, write pseudo-styles for the anchor tag:
a:link {
color:#F6C;
}
a:visited {
color: #6db285;
}
a:hover {
color: #f8cb43;
}
You don't have to use all five states; in fact you can use as few as one. However, if you do use several, they must occur in the following order to guarantee proper function: link, visited, focus, hover, active.
Of course color is just one of the properties of a link that can be specified with a pseudo-style. The default underlines can be removed with the text-decoration property. You can also have the font-sizes, font-weights, font-styles, font-families, etc. all change in each state. However, be aware that too many changes will create a visual and usability mess. One again, less is more.
Try this:
a:link {
color:#F6C;
text-decoration:none;
}
a:visited {
color: #6db285;
text-decoration:none;
}
a:hover {
color: #f8cb43;
text-decoration:underline;
}
This hides the line below the link until it is moused-over. Many designers prefer this because they hate the clutter created by all of the underlines in their perfectly designed text. But this causes usability problems—links are harder to spot which can lead to confusion and frustration on the user's part.
Another option is to make the underline more subtle; try this:
a:link {
color:#F6C;
text-decoration:none;
border-bottom:#15e45e 1px dotted;
}
a:visited {
color:#6db285;
text-decoration:none;
border-bottom:#6db285 1px dotted;
}
a:hover {
color: #f8cb43;
text-decoration:none;
border-bottom:#f8cb43 1px dotted;
}
This approach uses the border property to add a more subtle dotted line below the links. They're still visible, but they don't overwhelm the text like solid underlines.
Fancy underlines
In general it is best the links remain underlined because that is the convention everyone is used to. Users don't want to figure out new conventions for every page they visit. If a user can't make sense of your site, he'll leave. So resist the temptation to do something really radical.
Instead, try a subtle variation on the convention. Check out this link: Fake example link. Note the cool underline; it was created by using a simple graphic. You can download a copy of the graphic here with some others we'll use later, or make your own. To apply it, try this code:
a.fancy {
color:#0f22EC;
text-decoration: none;
background: url(linkGraphics/underline1.png) repeat-x left bottom;
border-bottom:none; /* this is needed because we added borders to all links in a previous style rule */
}
I've also included a file called underline2.png. Try that out as well.
Now check out this one: Fake example link 2. Looks the same? Try hovering over it. You should see the "line" start to move like a marquee. I created an animated .gif and used it for the over state (I included the animated .gif in the download folder above). Here's the new line o' code:
a:hover.fancy {
background-image:url(linkGraphics/underline1Animation.gif);
}
Be aware that not every browser can handle an animated .gif as a background. Also, be aware that animated elements could be annoying, or foul up accessibility guidelines. Use with discretion.
Differentiating between different kinds of links with CSS 3
We can go further still and use CSS to differentiate between different kinds of links. For example, we can make a link to an external site look different than one to a local page. We can even make links to downloadable files like .pdfs visually different than links to html pages. We accomplish this by using attribute selectors. One word of caution, these selectors are part of CSS 3, so not all browsers will support them. Firefox and Safari do however.
Check out these links:
Here's how we do it:
a[href^="http:"] {
color:#0C0;
background: url(linkGraphics/externalLink.png) no-repeat top right;
padding-right: 18px;
border-bottom-color:#0C0; /* not needed if your using regular text-decoration:underline */
}
a[href$=".pdf"] {
color:#F00;
background: url(linkGraphics/pdfGraphic.png) no-repeat top right;
padding-right: 18px;
border-bottom-color:#F00; /* not needed if your using regular text-decoration:underline */
}
The ^ character (shift-6) allows me to select all attributes that start with "http:", in other words, external links. However, it will also pick up any internal links that use absolute path names with http, so make sure you use only relative urls within your site.
The $ character allows me to select attributes that end with ".pdf." You could also create separate styles for links ending with .doc or .rss or .xml or .swf or any other extension.
In both cases, I've created a special custom icon (included in your download above), that I place as a background, then set to the right. By adding extra padding, I create room for the icon (otherwise it would appear behind the text).
Oh, what happens when you try to view these links in an older or crappy browser? Nothing; they ignore the styles and display them as "normal" links. Consider this technique a bonus for folks who have enough sense to use a decent browser.
Turning links into buttons
So what if you want something that looks and feels more like a button? The key is to set the display property of the link to block. This will make the area around the text "clickable" as well, giving you a larger hit area. Setting a size and a background color complete the effect:
Here's the css:
a.basicButton {
background-color: #FF9;
display: block;
width:8em;
text-align:center;
text-decoration:none;
line-height:1.4;
padding: .2em;
border: 1px solid #000;
color: #C00;
}
a:hover.basicButton {
background-color: #FF0;
color:#F00;
}
I used line-height instead of height because line-height automatically centers the text vertically. I also used ems for the width; this way if the user zooms the text, the entire button will expand. If you wand a fixed size, use pixels (but be aware that text may push itself outside of the box if zoomed).
A rollover effect can be created by adding a hover pseudo-style and changing the background and/or text colors.
Add a splash of CSS 3...
You can add rounded corners to your buttons by using CSS 3 properties:
a.basicButton {
background-color: #FFFF99;
display: block;
width:8em;
text-align:center;
text-decoration:none;
line-height:1.4;
padding: .2em;
border: 1px solid #000;
color: #C00;
border-radius: 7px;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
}
Once again, CSS 3 is not fully implemented. Your buttons will remain square in IE, for example.
You could turn this graphic into a tab-styled button by rounding out only the top two corners, like this:
a.basicButton {
background-color: #FFFF99;
display: block;
width:8em;
text-align:center;
text-decoration:none;
line-height:1.4;
padding: .2em;
border: 1px solid #000;
color: #C00;
border-radius: 10px 10px 0 0;
-moz-border-radius: 10px 10px 0 0;
-webkit-border-radius:10px 10px 0 0;
}
Graphical buttons
Okay, say you want a button to have a cool background—gradients or reflections or something similar. Well then you'd have to use a background image; no problem. But what if you wanted the graphic to change on a rollover? You could simply create two images and set them to be the backgrounds of a:link and a:hover respectively. However, there will be an undesirable delay and/or flicker the first time the button is moused-over while the second image loads. A better way is to combine both images into one graphic, and then simply show only the applicable portion for each state. Confused? Let's try it out. Here's a button in action:
Now, here is the graphic I used; you'll find a copy of it in the folder of graphics you downloaded above.

And now the code:
a.graphicButon {
display: block;
width:160px;
height: 40px;
line-height:40px;
text-align:center;
text-decoration:none;
color: #A5B2F9;
background: url(linkGraphics/fancyButtons.jpg) no-repeat left top;
border-bottom:none; /* this is needed because we added borders to all links in a previous style rule */
}
a:hover.graphicButon {
background-position: left bottom;
color: #FFF
}
Note that the background is twice the size of the button. In each state only part of the background image (top half or bottom half) is visible. The rollover cause the background to be repositioned, essentially sliding it up and down. Pretty cool, eh?
Alas, sucky IE will still flicker because it will want to reload the image from the server even though there is no need. You could say "screw 'em, get a real browser!" or you could add a clever fix. Wrap the link in a container element (like a paragraph) and apply the same background image to it. This way when the link image vanishes for an instant, the same image will be visible underneath, so the user will see no flicker.
You can do the same thing with three states (an 'active' state) or more. Simply add the additional button states to the button. Then in the CSS instead of using 'top' and 'bottom,' you'll have to use specific pixel amounts. Measure carefully!
Here's an exercise that walks you through the process of creating a full navbar using this technique.
Sliding Door Tabs
One last cool trick. Say you want to use tabs at the top of your page for navigation. You could create a simple tab graphic and use it as a background as above. But if the user zooms the text, the tab will stay the same size. Likewise, you may have some tabs that need to be wider than others to accommodate longer link names. One solution is to create a 'sliding door' tab, basically a tab with two overlapping graphics that expand as the text expands. Here is a sample:
Here are some sample graphics you can use:
![]()
Since there are two background images, we need two tags to hang the styles on. Above we placed my <a> tags inside a paragraph <p>, but you could also u
p.slidingDoor {
background:url(linkGraphics/tabLeft.png) no-repeat top left;
float:left; /* prevents the paragraph from stretching across the page */
margin-right:1px;
}
p.slidingDoor a {
display: block;
padding: .5em 1em;
text-decoration:none;
color: #DDD;
background:url(linkGraphics/tabRight.png) no-repeat top right;
border-bottom:none; /* this is needed because we added borders to all links in a previous style rule */
}
p.slidingDoor a:hover {
color:#FFF;
}
I placed one of the images as a background on the paragraph, and the other on the anchor tag. The smaller (right-hand) graphic floats above the left graphic, sliding back and forth as the text changes size. It's important to float these, otherwise the tabs will stretch to the width of the containing element (in this case the whole page).
The one limitation with this method is that you can't change the background image on a rollover. You can change the text (style, color, weight, decoration, etc.) but since the background is actually composed of two images on two tags, you can't change them both...for now. Once IE starts supporting pseudo-classes for non-anchor tags, we'll be able to write a p:hover style; this will allow us to change both background images simultaneously.