Formatting a tag cloud with CSS

Share on TwitterShare on TumblrSubmit to StumbleUponSave on DeliciousDigg This

In this article I’ll explain how to format a tag cloud by using CSS. Tag clouds are a semantic feature of the so-called Web 2.0. The picture below shows an example of tag cloud.

A tag cloudFigure 1. A tag cloud

The arrows represent the semantic relationship between the various tags. Positioning, fonts and colors can be specified through CSS, as we’ll see below.

Table of contents

The markup

The markup used here is pretty simple and is as follows:

Listing 1. Proposed markup for a tag cloud

  1. <ul id="tag-cloud">
  2. <li id="css"><a href="#">CSS</a></li>
  3. <li id="xhtml"><a href="#">XHTML</a></li>
  4. <li id="ia"><a href="#">IA</a></li>
  5. <li id="wiki"><a href="#">Wiki</a></li>
  6. <li id="web20"><a href="#">Web 2.0</a></li>
  7. </ul>

View the example

We use an unordered list because we’re inserting a series of elements. As you can see, this allows us to keep the sense of a succession even if the styles are disabled. Futhermore, we’ve assigned an ID to each list item in order to give different styles to each tag in the cloud.

Preparing the positioning

Since each tag will have a different position inside the cloud, we can use absolute positioning to accomplish this task. When an element is absolutely positioned, however, its position is calculated by taking the viewport as reference. If we want to change this default behavior, we have to declare as relatively positioned the parent element of our target elements. In this case, the elements will be positioned by taking their parent element as reference. This is called a contextual positioning. The relevant code is as follows:

Listing 2. Creating a contextual positioning

  1. #tag-cloud {
  2. margin: 0;
  3. padding: 0;
  4. width: 100%;
  5. position: relative;
  6. }
  7. #tag-cloud li {
  8. display: block;
  9. }

View the example

Now the tags will be positioned by taking #tag-cloud as reference. The second rule is important here, because by declaring a list item as a block-level element we actually get rid of the list markers. Unfortunately, this declaration has no effect in Internet Explorer 7 and lower, but only in this case Explorer won’t show any bullet at all, since we’ve zeroed margins and padding of the list so that there’s no more space left for list markers.

Positioning the tags

As said above, we’ll use absolute positioning on the tags in the cloud. The rules are the following:

Listing 3. Positioning the tags

  1. #tag-cloud li {
  2. display: block;
  3. position: absolute;
  4. }
  5. #tag-cloud #css {
  6. top: 0;
  7. left: 0;
  8. }
  9. #tag-cloud #xhtml {
  10. top: 0;
  11. right: 2em;
  12. }
  13. #tag-cloud #ia {
  14. top: 2em;
  15. left: 40%;
  16. }
  17. #tag-cloud #wiki {
  18. top: 4em;
  19. left: 0;
  20. }
  21. #tag-cloud #web20 {
  22. top: 4em;
  23. right: 1em;
  24. }

View the example

In order to have the maximun flexibility, we’ve used relative lengths and percentages to position the tags. What’s more, the tags have no specified dimensions. In this case, the specifications state that it will be applied the “shrink-to-fit” algorithm, that is, the dimensions of the elements will be determined by the amount of content inside them. In other words, the elements will be wide enough to host their content, but nothing more.

Styling the tags

The styles for the tags are all related to colors and typography, as you can see in the following code.

Listing 4. Styling the tags

  1. #tag-cloud a {
  2. text-decoration: none;
  3. }
  4. #tag-cloud #css a:link,
  5. #tag-cloud #css a:visited,
  6. #tag-cloud #css a:hover {
  7. text-transform: uppercase;
  8. color: #fa0;
  9. font: bold 1.6em/normal Arial, sans-serif;
  10. }
  11. #tag-cloud #xhtml a:link,
  12. #tag-cloud #xhtml a:visited,
  13. #tag-cloud #xhtml a:hover {
  14. text-transform: lowercase;
  15. color: #0af;
  16. font: bold 2em/normal "Trebuchet MS", Trebuchet, sans-serif;
  17. }
  18. #tag-cloud #ia a:link,
  19. #tag-cloud #ia a:visited,
  20. #tag-cloud #ia a:hover {
  21. color: #0c0;
  22. font: bold 3em/normal Impact, sans-serif;
  23. }
  24. #tag-cloud #wiki a:link,
  25. #tag-cloud #wiki a:visited,
  26. #tag-cloud #wiki a:hover {
  27. color: #999;
  28. font: small-caps 4em/normal "Arial Narrow", Arial, sans-serif;
  29. text-transform: lowercase;
  30. }
  31. #tag-cloud #web20 a:link,
  32. #tag-cloud #web20 a:visited,
  33. #tag-cloud #web20 a:hover {
  34. color: #c0c;
  35. font: bold 1.2em/normal Georgia, serif;
  36. text-transform: uppercase;
  37. }

View the example

As you can see, we’ve only specified fonts and text colors for the various tags. It’s important to notice two things here: first, we’ve specified a fallback value for the font-family property (sans-serif or serif) to deal with the fact that some operating systems (mainly Unix-based ones) could not have the specified fonts. Second, we’ve reduced the line-height to normal and used the text-transform property to control the capitalization of text.

Adding a flickering effect

Finally, we want to add a flickering effect to the tags in order to make them change their position in a random order. Usually we’d use JavaScript to fulfill this goal, but in this case a simple CSS rule is sufficient.

Listing 5. Adding a flickering effect

  1. #tag-cloud li:hover {
  2. position: static;;
  3. }

View the example

Did you notice what’s happened? Since the tags are absolutely positioned, they’re actually taken out of the normal flow. This rule simply puts them in the normal flow but only when the user hovers the elements with the mouse, that is, just for a few seconds. Then they are taken again out of the normal flow, and so on.

However, Internet Explorer 6 doesn’t support the :hover pseudo-class on all elements, but only on hyperlinks. So we have to use an HTC file (developed by Peter Nederlof) to enable this behavior in Explorer 6.

Listing 6. Adding a HTC file for Internet Explorer 6

  1. <head>
  2. <!--[if lt IE 7]>
  3. <style type="text/css" media="screen">
  4. body {behavior: url(csshover.htc);
  5. </style>
  6. <![endif]-->
  7. </head>

In any case, this flickering effect should be avoided for accessibility reasons.

Bulletproofing the layout

As we’ve just seen above, the structure of the tags inside the cloud is made up by five elements. All these elements are absolutely positioned, and this is fine for tag clouds with few elements. However, when the number of elements increases, there could be some problems with the positioning of elements. So we should keep some elements in the normal flow while absolutely positioning the others. To solve this problem, we can use a particular feature of absolute positioning, namely the auto value of the top property. For example:

Listing 7. The auto ‘auto’ value of the ‘top’ property

  1. #tag-cloud #ia {
  2. position: static;
  3. text-align: center;
  4. padding-top: 2em;
  5. list-style: none;
  6. }
  7. #tag-cloud #wiki, #tag-cloud #web20 {
  8. top: auto;
  9. }

View the example

The #ia element is the third item in our list. Then come #wiki and #web20. By declaring position: static on the third item, we actually put it in the normal flow. Then we declare top: auto for the following elements, #wiki and #web20. By doing so, the elements will be vertically positioned exactly under the #ia element, that is, the preceding element in the normal flow. The auto value of the top property allows us to position an element exactly after an in-flow, non-positioned element that precedes a positioned element in the document tree, as we can see in the following figure, that shows an excerpt from the document tree.

The DOM tree of our cloudFigure 2. The DOM tree of our cloud

As we can see, the #ia, #wiki and #web20 elements are actually siblings, so that they are on the same level in the document tree. Finally, we’ve used list-style: none on the #ia element in order to prevent Internet Explorer 7 (and lower) from showing the list marker. After putting this element in the normal flow again and centering its text horizontally, Explorer “thinks” that now the space is sufficient for showing the list marker.

Download examples