Clickable <li>

When designing this site, I set out to make it as simple as possible. I opted to just give you basic post information on the home page. I originally coded the markup to be a table, but discovered a problem when I tried to make the whole row clickable. I ended up with a list of articles instead.

Look at what we’re going to accomplish in this article:

  • Before Demo Table-based
  • After Demo ul Goodness

How I Want the Row to Behave

This is best illustrated with a video example from the new iTunes store.

Notice how you can click anywhere in the row to get the song to play. The hover state lets you know that it is all clickable.

How The Markup Started

I started with a table-based list of articles. It was easier to make the design align to my layout grid with a table. I justified the use of the “HTML element that shall not be named” by convincing myself that the data was mostly tabular. A column for each category, title, and summary made sense to me.

You can see the original design here. Basically, the markup looked like this:

<table cellpadding="0" cellspacing="0">
  <colgroup>
    <col id="category" />
    <col id="title" />
    <col id="summary" />
  </colgroup>

  <tbody>
    <tr>
      <td>
        <a class="#">Usability Review</a>
      </td>
      <td>
        <h2><a class="#">Typekit</a></h2>
      </td>
      <td>
        <p>Excerpt goes right her'</p>
      </td>
    </tr>
  </tbody>

</table>

Semantically, this was probably fine, but it felt dirty when I tried making the whole table row a single link. The only way I found to do that involved three separate heavily padded links to the same place and some absolute positioning to make it look good. That created a lot more problems than it solved. After four hours of hacking at different markup and CSS, I decided to try a different approach.

Converting to an Unordered List

I thought about what this element really was and it is a list of articles, starting with the most recent. I thought to myself:

If this is a list of articles, why am I using a table to mark it up? It could be done much better with an unordered list (<ul>).

Converting this particular element to a list gives me a warm semantic butterflies in my stomach.

Semantic Butterflies

<ul>

  <li id="post-1">
    <a class="#post">

      <span>Usability Review</span>
      <strong>Typekit</strong>
      <em>Web app for embedding custom fonts in your design that will change the way you approach web typography.</em>

    </a>
  </li>

</ul>

This markup isn’t ideal for two reasons:

  1. I’m using extra elements (like the span, strong and em)
  2. I cannot use my h2 element for the post titles because links cannot surround block-level elements like ps or h2s. I’m losing some search engines benefits and some semantificity (I just made that word up), but strong is a good substitute.

For now, I’ll have to live with this if I want to make the entire list item a link, but there is some hope for the future. Eric Meyer proposed any element linking in which you could give any element an href property. Wouldn’t it be nice to be able to do this in HTML 5?

<p class="linktosomething.com">This entire paragraph will appear as a clickable link</p>

or

<tr class="linktosomething.com">
  <td>Every bit</td>
  <td>in this table row</td>
  <td>will be clickable</td>
</tr>

Currently, Eric’s solution works in a limited number of browsers and uses some inline Javascript to work its magic. Check out the demo if you want to see his markup.

There is still hope that any element linking will be easier in the future, but that doesn’t solve your problem now.

What Works Now

Now that we have the markup stashed away and validated (you better be validating, mister!), we can move onto making it look nice with CSS.

Expanding the Link to Fill the Entire Row

The most important part of this code is making each link a fill up the entire row. Imagine pouring water into a clear square box. It will naturally expand to fill its container. Our entire goal with this technique is make each post link more usable by increasing the entire clickable area. Currently, only the text is clickable.

spacer

We can make the link act like H2O by making each link inside a list item a block. I’m giving the link a light blue background when it’s hovered over to let the viewer know the entire row is clickable.

ul.posts li a { border: 0; display: block; overflow: hidden; }
ul.posts li a:hover { background-color: #DBF1F9;/* light blue */ }

Next, we’ll float the different pieces of data to where we want them. Categories goes all the way to the left, title in the middle, and post excerpt to the right.

ul.posts span.category { float: left; }
ul.posts strong.title { float: left; }
ul.posts em.excerpt { float: right; }

Easy enough. There is no float: middle so for the title, we float it left too. It ends up bumping up against the category block keeping it in the center.

spacer

Floating isn’t effective because we still need to give each piece of data a width and padding so it has some room to breath. When trying to make something simple and easily scannable, white space is your friend.

ul.posts span.category { float: left; .2%; }
ul.posts strong.title { float: left; .4%; }
ul.posts em.excerpt { float: right; .4%; }

ul.posts span.category,
ul.posts strong.title,
ul.posts em.excerpt { padding: 3% 1% 2% 0; }

Where the hell did I get those widths?!

I actually just made them up! The skillful designer in me told me that 38.4% was the way to go.

Just kidding. I actually used a mathematical formula to figure it out (and you thought you were done with math in high school). Instead of giving each element a fixed width, I went with a percent to give the design fluidity.

Here’s how to convert from a fixed width element to a percentage:

  1. Determine the element’s desired width (300px for the title) and the width of the containing element (760px).
  2. Divide the desired width by the width of the container. (300px/760px)
  3. Convert that to a percentage. (0.394 is 39.4%)
  4. Subtract any padding (1% on the right)
  5. Ta-da! You have your width in a percentage. (38.4%)

I got the width of the containing element by seeing how many columns it spans in my grid system. I use the 960 grid system for my layouts. If you’ve never used a grid system, I recommend trying one out, at least while first laying out your design.

spacer

The layout is there and the entire row is clickable (denoted by the blue). We need to style it so it looks pretty (as a designer, I tend to like pretty things).

Prettifying It

Let’s put a border beneath each item, a border at the tippy top of the list for balance, and ditch that bullet point.

ul.posts { border-top: 1px solid #ddd; list-style: none; }
ul.posts li { border-bottom: 1px solid #ddd; }

spacer

Let’s add some finishing touches to make attract attention where it is most important. I want viewers to first see the title, so I’ll make that the darkest and the biggest (basically mimic what an h2 normally looks like). If the title strikes their fancy, I want them to read the one sentence excerpt about the post. Lastly, I want them to see the category on the left, so I’ll make that the lightest.

ul.posts span.category { color: #888; color: rgba(0,0,0,0.47); padding: 4% 1% 4% 0; }
ul.posts strong.title { color: #333; color: rgba(0,0,0,0.8); px; font-weight: bold; line-px; margin: 0; }
ul.posts em.excerpt { color: #555; color: rgba(0,0,0,0.66); font-style: normal; }

Note about the rgba: I like to use rgba when coloring something a shade of gray because it allows me to adjust the visual weight straight from the code. If I want something to be less important (like the category), I’ll knock its opacity down (the a part of rgba). Once I’ve found a shade I like, I convert it to a regular hex color so older browsers still color it appropriately.

I put the hex color code first because older browsers will just ignore the rgba if they don’t understand it. I keep the rgba color there to give modern browsers a bit of snazzy styling. If I had a background color on the whole page (blue for example), the semi-opaque gray text would pick up the slightest hint of blue because the background would show through. Dan Cederholm talks extensively about this subtle visual effect in his new book Handcrafted CSS.

spacer

We end up with a minimalist and usable clickable list item that uses valid HTML and CSS code. Check out the live demo to see the final result in action.

Here’s the complete CSS code for reference:

ul.posts li a { border: 0; display: block; overflow: hidden; }
ul.posts li a:hover { background-color: #DBF1F9;/* light blue */ }

ul.posts span.category { float: left; .2%; } /* 160/760px - 1% padding */
ul.posts strong.title { float: left; .4%; } /* 300/760px - 1% padding */
ul.posts em.excerpt { float: right; .4%; } /* 300/760px - 1% padding */
ul.posts span.category, ul.posts strong.title, ul.posts em.excerpt { padding: 3% 1% 2% 0; }

ul.posts { border-top: 1px solid #ddd; list-style: none; margin-right: 40px; }
ul.posts li { border-bottom: 1px solid #ddd; }
ul.posts span.category { color: #888; color: rgba(0,0,0,0.47); padding: 4% 1% 4% 0; }
ul.posts strong.title { color: #333; color: rgba(0,0,0,0.8); px; font-weight: bold; line-px; margin: 0; }
ul.posts em.excerpt { color: #555; color: rgba(0,0,0,0.66); font-style: normal; }

I tested this code in IE7, IE8, Safari and Firefox (for Mac and Windows).

# Usability Tip tags: :hover, Fitt's Law, li, target area on Oct 13, 2009

10 Comments

  1. Martin says: Oct 20, 2009

    Loves it! As you said, it’d be wonderful if we could link the whole paragraph/table row as proposed for HTML5, but it’s going to have to wait (that’s if it ever makes it to the final spec).

    I can see me implementing this throughout several projects where “semantificity” isn’t that much of an issue (internal software development)…

    Thank you for an interesting post!

  2. mike says: Oct 20, 2009

    So not cool that you cant select any of the text in the rows…

  3. Kevin says: Oct 20, 2009

    @Mike,

    That is definitely a usability pitfall with this method. I considered this and decided that for this particular situation, users wouldn’t need to highlight text that much. The goal of making this entire list item clickable is to get them to the article (where they can then select text to their hearts desire).

    If you wanted to keep the text selectable, you could have the same layout, but multiple links surrounding each one of the columns. All of these links would point to the same place. You would also need to fake a unified hover state on the entire li, which isn’t supported in a few browsers (other than with a single a).

    You can check out Digg for an example of this. It’s not the same layout as this one, but it’s the same concept. Notice how the the paragraph description for each story is linked.

  4. omBRE says: Oct 21, 2009

    what about frkn IE6?

  5. Kevin says: Oct 21, 2009

    @omBRE,

    I’ve chosen not to support IE6 with this site (and actually every other site I make). It takes up too much of my time to pander to such an outdated browser. I’d rather take my time and make the experience better for modern browser users.

    I serve up an unstyled version of the site if the user happens to be in IE6.

  6. Nokadota says: Oct 21, 2009

    This is fantastic and really improves UX in my opinion. Thank you for the article, I hope to use this technique in my future projects.

  7. mike says: Oct 21, 2009

    Hehe Digg is one of the sites that bother me because when i want to send a link to a friend i might not want to include the hole description but i have no choice but to select the entire paragraph if i want to copy and paste.

  8. Brett says: Oct 21, 2009

    This is a beautiful solution, and I personally agree with the concept of making nice large click-areas for users and giving substantial user feedback via the hover state.

    One concern though: I feel like the solution has LOST some functionality. In the original code example, you’re able to click the category in order to sort posts using that category. Your solution does not have the capability. I don’t know if that had been considered, but if it had, may I ask why you decided to drop that functionality off the list?

  9. Kevin says: Oct 28, 2009

    @Brett,

    I did like the functionality of the previous version because of that category link. Because I’m surrounding everything in the with a link, there is no way to keep that functionality. I cannot have a link within a link.

    I decided that it was best to have the largest clickable area possible because I link to my categories in the navigation that appears on every page, but that could change depending on the context. If I didn’t have the categories in the navigation, I would think twice about the usability of the design at all. Readers would have no idea how to get to a specific category page.

  10. rachel says: Aug 5, 2010

    wow thank you so much for this.

gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.