Rotated Table Column Headers

Avatar of Chris Coyier
Chris Coyier on (Updated on )

Say you have a table header (i.e. <th>) of “Number of Howler Monkey Species by Country” and the data in the corresponding <td> is like “3”. That’s an awkward mismatch of width.


Perhaps not a huge problem for two columns, but if you had 20 that would be very hard to navigate and a poor use of space. A better use of space is to rotate the headers so that the column width can be much narrower.

Rotating 90-degrees is too far though. It makes it hard to read.

Interestingly, we get just about the same amount of space saving if we rotate the headers 45 degrees instead, and they are much easier to read.

The Trick

There are a couple of tricks here.

We’re going to need to use transform: rotate() to angle the headers. Chrome/Safari lets you do that right on the <th>, but I had trouble with the text disappearing in Firefox that way, so let’s do that within a nested <div> that we’ll force to be the width we want the column to be (it also didn’t work to force the cell narrow directly). We’re going to need another nested element as well, so…

<th class="rotate"><div><span>Column header 1</span></div></th>
th.rotate {
  /* Something you can count on */
  height: 140px;
  white-space: nowrap;

th.rotate > div {
    /* Magic Numbers */
    translate(25px, 51px)
    /* 45 is really 360 - 45 */
  width: 30px;
th.rotate > div > span {
  border-bottom: 1px solid #ccc;
  padding: 5px 10px;

Note the magic numbers there. I bet some of you are smart enough to figure out the mathematical relationship to all the other numbers going on in there. In fact, my example started out life as a fork of Jimmy Bonney’s Column Header Rotation article. I was able to do it without the skew() stuff he was doing which I think makes it a bit simpler, but he also had figured out some math stuff using tan() and cos() which might be a good starting point if you start digging in yourself.


If you go down this road, you might wanna make sure you aren’t applying rules that screw up the table if the transforms don’t work. Modernizr can test for that and apply support/non-support classes to the <html> element, so you can write stuff like:

/* These aren't needed and will be weird if transforms don't work */
.csstransforms th.rotate {
  height: 140px;
  white-space: nowrap;

How you want to do the fallback is up to you, but it could be worse than just having the table be super wide:

My final demo has this in place.


It’s in Sass in case you want to fork it and figure out some awesome way to use variables and math and stuff to make it more adaptable.