A directory listing with CSS

Share on TwitterShare on TumblrSubmit to StumbleUponSave on DeliciousDigg This

In this article I’ll explain how to format a directory listing by using CSS. Usually a directory listing looks as follows.

A directory listingFigure 1. A directory listing in Apache

The markup used in the above directory listing is obsolete (HTML 3.2), non-semantical and with a low level of accessibility. Apache, the web server taken as example, uses an unique pre element to wrap the entire content of the listing and to format such content as a table. Our goal is simple: we want to format a directory listing by using CSS for the presentation and semantical XHTML for the structure, preserving at the same time the original layout.

Table of contents

Choosing the right markup

Since our data in the original layout are formatted as a table, we’ll use a real table in order to give to our users all the accessibility benefits related to table elements, in particular to the users of screen readers and other assistive technologies. The proposed markup is the following:

Listing 1. Proposed markup for a directory listing

  1. <table summary="Directory listing of /directory">
  2. <tr>
  3. <th scope="col">Name</th>
  4. <th scope="col">Last Modified</th>
  5. <th scope="col">Size</th>
  6. <th scope="col">Description</th>
  7. </tr>
  8. <tr>
  9. <td><a href="#" title="Parent Directory">Parent Directory</a></td>
  10. <td>22-Dec-2007 05:55</td>
  11. <td>-</td>
  12. <td>-</td>
  13. </tr>
  14. <tr>
  15. <td><a href="#">file.html</a></td>
  16. ...omission...
  17. </tr>
  18. <tr>
  19. <td><a href="#">file.pdf</a></td>
  20. ...omission...
  21. </tr>
  22. <tr>
  23. <td><a href="#">file.jpg</a></td>
  24. ...omission...
  25. </tr>
  26. <tr>
  27. <td><a href="#">file.zip</a></td>
  28. ...omission...
  29. </tr>
  30. <tr>
  31. <td><a href="#">file.mp3</a></td>
  32. ...omission...
  33. </tr>
  34. <tr>
  35. <td><a href="#" title="Go to 'Documents'">documents</a></td>
  36. <td>10-Dec-2007 09:00</td>
  37. <td>-</td>
  38. <td>-</td>
  39. </tr>
  40. </table>

View the example

As you can see, we’ve used two important attributes of table elements, namely summary and scope. The first adds a brief description of table contents and will be spoken aloud by screen readers. The latter associates each table header with its respective column and is very useful for table navigation. We can appreciate this new, semantical structure in the following screenshot taken from Lynx.

The markup viewed in LynxFigure 2. Our structure viewed in Lynx

Basic styles

We start with very simple styles.

Listing 2. Basic styles

  1. body {
  2. background: #fff;
  3. color: #000;
  4. }
  5. a:link, a:visited {
  6. color: blue;
  7. background: transparent;
  8. }

View the example

Note that we haven’t specified a different font family and hyperlinks color for the page, since we want to respect the default rendering of each browser.

Styling the table

We want to create a fluid table with top and bottom borders. These borders will replace the presentational hr element used in the original layout. The styles are the following:

Listing 3. Styling the table

  1. table {
  2. font-family: monospace;
  3. border: none;
  4. width: 90%;
  5. border-collapse: collapse;
  6. }
  7. td, th {
  8. width: 25%;
  9. vertical-align: top;
  10. padding-top: 0.3em;
  11. padding-bottom: 0.3em;
  12. }
  13. th {
  14. font-weight: normal;
  15. text-align: left;
  16. }
  17. .bordertop {
  18. border-top: 2px outset #ccc;
  19. }
  20. .borderbottom {
  21. border-bottom: 2px outset #ccc;
  22. }

View the example

First, we specify a generic monospaced font on the table. Again, we want to respect the default rendering of each browser. The width of our table is fluid, and the borders of its cells won’t have a blank space between them, since we’ve set the border-collapse property to collapse. The content of each cell will be vertically aligned on top and there will be a certain amount of top and bottom padding. The third rule resets the default font weight and text alignment of each table header. Finally, the last two rules create the effect of two horizontal rules thanks to a top and a bottom border, respectively. Since we want that these borders appear after the first and last row, we can’t specify them on the table itself.

Adding background images

Now we need to add a different background image to each type of file. The code is pretty simple.

Listing 4. Adding background images

  1. .parent, .text, .pdf, .image, .compressed, .sound, .dir {
  2. padding-left: 24px;
  3. height: 1.5em;
  4. }
  5. .parent {
  6. background: transparent url("img/back.gif") no-repeat top left;
  7. }
  8. .text {
  9. background: transparent url("img/text.gif") no-repeat top left;
  10. }
  11. .pdf {
  12. background: transparent url("img/pdf.gif") no-repeat top left;
  13. }
  14. .image {
  15. background: transparent url("img/image.gif") no-repeat top left;
  16. }
  17. .compressed {
  18. background: transparent url("img/compressed.gif") no-repeat top left;
  19. }
  20. .sound {
  21. background: transparent url("img/sound.gif") no-repeat top left;
  22. }
  23. .dir {
  24. background: transparent url("img/dir.gif") no-repeat top left;
  25. }

View the example

The relevant rule here is the first. By specifying a proportional height and a left padding on each cell, we assure ourself that the background images will be entirely visible. The other rules simply position the background images on the left top edge of each cell.

Finalizing the layout

At the very end of each directory listing there is an address element containing the relevant information about the web server and the host. The styles for this element are the following.

Listing 5. Finalizing the layout

  1. address {
  2. margin: 0;
  3. padding: 0.5em 0;
  4. }

We use vertical padding instead of margins in order to avoid some browsers oddities in the calculations of collapsing margins.

Bulletproofing the layout

To add more flexibility to our layout, we can write the following code.

Listing 6. Bulletproofing the layout

  1. .parent, .text, .pdf, .image, .compressed, .sound, .dir {
  2. padding-left: 1.8em;
  3. }

View the example

By using ems, the left padding of these cells will scale along with text while the user changes the default font size of the page.

Download examples