Vertical text for table headers with CSS

In complex tables with lots of columns you will run into the problem of headers being too wide and causing the table to stretch beyond the available width. One solution is to use vertical text to render the headers.

You can also achieve this using images, but by doing so you lose the benefits of text:

  • selectable,
  • resizable,
  • easier to style and update,
  • easier to dynamically generate.

With the CSS transform attribute it is possible to rotate things vertically.

div.vertical
{
 transform: rotate(-90deg);
 -webkit-transform: rotate(-90deg); /* Safari/Chrome */
 -moz-transform: rotate(-90deg); /* Firefox */
 -o-transform: rotate(-90deg); /* Opera */
 -ms-transform: rotate(-90deg); /* IE 9 */
}

For Internet Explorer version 8 and below you have to do it differently:

div.vertical
{
 writing-mode: tb-rl;
 filter: flipv fliph;
}

There are some caveats. Browsers usually apply the transform at the end, so we have to take this into account and adjust the width/height accordingly. If you don't adjust the size of the container, its width/height will be the same as if the text wasn't rotated.

In the case of a table we will use a div inside each table cell, so we have more control to style the outcome.

<table>
 <thead>
  <tr>
   <th class="vertical"><div class="vertical">Really long and complex title 1</div></th>
   <th class="vertical"><div class="vertical">Really long and complex title 2</div></th>
   <th class="vertical"><div class="vertical">Really long and complex title 3</div></th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>Example</td>
   <td>a, b, c</td>
   <td>1, 2, 3</td>
  </tr>
  (...)
 </tbody>
</table>

Due to the differences in rendering between IE8 and below and the others browsers we will use two different stylesheets.

For IE8 and below:

div.vertical
{
 position: relative;
 height: 210px;
 width: 45px;
 margin-left: 0;
 padding-right: 10px;
 writing-mode: tb-rl;
 filter: flipv fliph;
}

th.vertical
{
 padding-bottom: 10px;
 vertical-align: bottom;
}

For other browsers:

div.vertical
{
 margin-left: -85px;
 position: absolute;
 width: 215px;
 transform: rotate(-90deg);
 -webkit-transform: rotate(-90deg); /* Safari/Chrome */
 -moz-transform: rotate(-90deg); /* Firefox */
 -o-transform: rotate(-90deg); /* Opera */
 -ms-transform: rotate(-90deg); /* IE 9 */
}

th.vertical
{
 height: 220px;
 line-height: 14px;
 padding-bottom: 20px;
 text-align: left;
}

Here is a screenshot of the final result:

PS: If you use this code in a local file in IE8, it will display a warning because of the filter that's being used. You can enable it without problems. That warning is not displayed if you place the files in a server.

Nuno Freitas
Posted by Nuno Freitas on December 17, 2013

Related articles