Rocking icons with CSS

<transmission>

Per the request of a few friends, I've written this tutorial to show a few tricks you can use to style icons and logos using semantic code and a little CSS. See the credits for some great references.

Basic, semantic HTML

First, write your basic HTML. An unordered list makes the most sense for a list of websites. I use the title attribute on links for basic accessibility.

<ul>
  <li><a href="http://twitter.com/ackernaut" title="Twitter">Twitter</a></li>
  <li><a href="http://www.facebook.com/ackernaut" title="Facebook">Facebook</a>
  <li><a href="http://delicious.com/ackernaut" title="Delicious">Delicious</a></li>
  <li><a href="http://www.vimeo.com/ackernaut" title="Vimeo">Vimeo</a></li>
  <li><a href="http://dribbble.com/players/ackernaut" title="Dribbble">Dribbble</a></li>
</ul>

Using a traditional CSS image sprite

This demo uses a traditional image sprite where all the states have been styled. This demo requires a larger image sprite and more CSS than demo two. However, the PNG image sprite has transparent negative space so it will work over any background color, texture or pattern as the design dictates. An image sprite can be easy to update and maintain with a well-organized working document created by your favorite pixel-pushing program.

Demo One

The CSS is pretty basic. You have to style the <a> elements to hide the text and give them square dimensions so that the image sprite shows as the background image. You simply float the <li> elements left or right, or you can let them stack up vertically per layout.

Consider usability when deciding on the size of the icons. Don't be afraid to go big! I see usability benefits when I design with larger elements and text as long as the layout and proportions are strong. Also, your visitor may be using a touchscreen device, such as an iPad, and the hover interaction will not matter.

/* Style icon links */
.icon-demo {
  clear:left;
  list-style:none;
  margin:35px 0;
  overflow:hidden;
  padding:5px 0;
}
.icon-demo li {
  float:left;
  margin:0;
  padding:0;
  width:96px;
}
.icon-demo a {
  display:block;
  height:0;
  margin:0 20px 0 0;
  overflow:hidden;
  padding:77px 0 0;
  width:76px;
}
.icon-demo a:focus {
  outline:none;
}

Defining background image position

Now set up the values for the background image. You will have to define background-position for each state of each link. I have included both :visited and :focus for improved usability.

Note: There is apparently a security feature used by Webkit that disables certain background changes for the :visited psuedo-class. See this thread on SitePoint

Once again, this demo requires more CSS than demo two.

/* Image sprite for demo one */
.one a {
  background-color:none;
  background-image:url(/space-station/tutorials/css-icons/assets/css-icon-demo.png);
  background-position:0 0;
  background-repeat:no-repeat;
}
.one .twitter {background-position:0 0}
.one .facebook {background-position:-76px 0}
.one .delicious {background-position:-152px 0}
.one .vimeo {background-position:-228px 0}
.one .dribbble {background-position:-304px 0}
.one .twitter:visited {background-position:0 -77px}
.one .facebook:visited {background-position:-76px -77px}
.one .delicious:visited {background-position:-152px -77px}
.one .vimeo:visited {background-position:-228px -77px}
.one .dribbble:visited {background-position:-304px -77px}
.one .twitter:hover, .one .twitter:focus {background-position:0 -154px}
.one .facebook:hover, .one .facebook:focus {background-position:-76px -154px}
.one .delicious:hover, .one .delicious:focus {background-position:-152px -154px}
.one .vimeo:hover, .one .vimeo:focus {background-position:-228px -154px}
.one .dribbble:hover, .one .dribbble:focus {background-position:-304px -154px}
.one .twitter:active {background-position:0 -231px}
.one .facebook:active {background-position:-76px -231px}
.one .delicious:active {background-position:-152px -231px}
.one .vimeo:active {background-position:-228px -231px}
.one .dribbble:active {background-position:-304px -231px}

Using a sprite with CSS3 transitions

Demo Two

This is bested viewed with a browser that supports transitions such as Chrome, Safari, a beta version of Firefox, or Opera.

In this version I am using a white PNG as an image sprite where the positive space is transparent. Therefore the background color shows through. I then add some CSS3 transitions to both the relative positioning and the background color for the desired effect.

This demo uses a smaller image sprite and less CSS than demo one, but the background color around the icons is limited to the color of the negative space of the image sprite. Of course this is white in this case. You can easily create versions with other colors with a well-organized working document.

/* Icon link setup for demo two */
.two a {
  background-color:#3D6666;
  background-image:url(/space-station/tutorials/css-icons/assets/css-icon-demo-cutout.png);
  background-position:0 0;
  background-repeat:no-repeat;
  position:relative;
}
.two a:visited {
  background-color:#5C9999;
}
.two a:hover, .two a:focus {
  background-color:#14CCCC;
  top:-5px;
}
.two a:active {
  background-color:#FF734C;
  top:0;
}
.two .twitter {background-position:0 0}
.two .facebook {background-position:-76px 0}
.two .delicious {background-position:-152px 0}
.two .vimeo {background-position:-228px 0}
.two .dribbble {background-position:-304px 0}

Defining CSS3 transitions

You'll see that I've used the transition properties specific to various browsers, as well as the universal property that we expect to have one day.

Update:
CSS transitions and other properties are possible in Firefox 4 Beta:

Firefox 4 Beta 2 is here — Welcome CSS3 transitions

/* Transitions for demo two */
.two a, .two a:visited {
  -moz-transition:background-color .6s ease-out 0, top .6s ease-out 0;
  -o-transition:background-color .6s ease-out 0, top .6s ease-out 0;
  -webkit-transition:background-color .6s ease-out 0, top .6s ease-out 0;
  transition:background-color .6s ease-out 0, top .6s ease-out 0;
}
.two a:hover, .two a:focus {
  -moz-transition:background-color .15s ease-in 0, top .15s ease-in 0;
  -o-transition:background-color .15s ease-in 0, top .15s ease-in 0;
  -webkit-transition:background-color .15s ease-in 0, top .15s ease-in 0;
  transition:background-color .15s ease-in 0, top .15s ease-in 0;
}
.two a:active {
  -moz-transition:background-color .075s ease-in 0, top .075s ease-in 0;
  -o-transition:background-color .075s ease-in 0, top .075s ease-in 0;
  -webkit-transition:background-color .075s ease-in 0, top .075s ease-in 0;
  transition:background-color .075s ease-in 0, top .075s ease-in 0;
}

Designing an image sprite

I typically create my image sprites in Photoshop. There are lots of tools for creating sprites and figuring out the background position but this is what works for me.

The most helpful task is lining up the graphical elements that make up the sprite. I line up the elements vertically or horizontally depending on how I intend to use the sprite, but you will learn that the position of the elements doesn't really matter in many cases.

If all the icons are the same size, or very similar, then it is easy to align them to a grid. I typically give each icon a pixel or two of padding to prevent any clipping that could happen if the user zooms in and out with the browser etc. In the case of icons I will make the height and width of the grid lines the same as the height and width of the icons on the webpage.

You can always go back to this document later if you want to tweak the design. If you keep the same grid, then all you have to do is upload a new version of the sprite image to your webserver.

Boo to Internet Explorer 6

If you want this to look good in IE6 then check out the CSS document for IE6. This document references a GIF instead of a tranparent PNG as well as a hack to resolve the IE6 flicker bug. There are some fancy solutions to make PNG images work in IE6. However, I have found that advanced CSS can push those solutions past their abilities.

Of course, to reference this document you need to add the conditional comments for IE6.

Edit: There are better ways of doing this, but you can still reference the conditional CSS to see how to (in a hacky way) force IE6 to cache background images. The rest of the CSS involves referencing images that aren't PNGs if you have not added PNG correction.

Check out these great posts on how to conditionally target different versions of IE and for applying PNG correction:

<!--[if IE 6]>
<link href="/space-station/tutorials/css-icons/assets/ie6.css" rel="stylesheet" type="text/css" />
<![endif]-->

Credit where credit is due

For these demos I used a great icon set by Gedy Rivera of Lifetree Creative. This set is clean, simple and very easy to use. You can purchase and download the icons on the Lifetree Creative website.

Also, I've restyled the <pre> and <code> elements for code examples for my site by referencing a great tutorial by Soh Tanaka.

And finally, check out Trent Walton's article “Non Hover” as he considers how users interact with our sites with touchscreen devices.

I hope this tutorial is helpful. Leave some feedback with questions or suggestions.

</transmission>

9 comments

Dave Rupert

Awesome! Love the use of the knockout positive space for the color. It definitely brought down the complexity of your CSS. wonderful transitions too!

Markus Vad Flaaten

Haven’t read it yet, but will surely do it some day. :)
Had a quick peep and it looked really awesome, actually learned some new stuff just from peeping.

Thanks in advvvance!

Leave a comment