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.
![](https://i0.wp.com/css-tricks.com/wp-content/uploads/2014/03/too-wide-table.png)
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.
![](https://i0.wp.com/css-tricks.com/wp-content/uploads/2014/03/90-deg.png)
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.
![](https://i0.wp.com/css-tricks.com/wp-content/uploads/2014/03/45-deg.png)
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 {
transform:
/* Magic Numbers */
translate(25px, 51px)
/* 45 is really 360 - 45 */
rotate(315deg);
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.
Fallback
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:
![](https://i0.wp.com/css-tricks.com/wp-content/uploads/2014/03/ie8-table.png)
My final demo has this in place.
Demo
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.
Can you apply that curved path for text?
Two word lengths straight, then a slight curve begins to end in 45º
Any reason not to use the more readable “rotate(-45)” instead of “rotate(315)”?
Good point, feel free.
Great article:)
However, The demo does’nt work.
It can’t read the Modenizr script.
CodePen bug, we’re on the case. I’m gonna bury this because I already fixed it in the short term.
Remember, you can use
writing-mode: tb-lr;
for IE<9, eventually adding the legacyfilter: flipv fliph;
.Not gonna try filters for the 45 deg text…
This is nice, thank you !
But if you have a mix between rotated and non rotated header cells you have to revert
to 90 degree rotation and vertically align the text to the bottom. It gets more complicated if you
have multiple text lines as header cell content, or rotated header cells of different length.
If all this can be handled entirely with CSS , fantastic !
Let us know.
Sadly, on Chrome, Firefox, and Opera the text spacing and baseline end up being uneven. IE10 looks great, but the others are raggedy.
Ooooh. Fancy. Thanks for sharing.
Looks just fine in my Firefox.
What is SCSS ?
Kind of off topic Mohit, but a legitimate question. SCSS is the evolved syntax of SASS (Syntactically Awesome Style Sheets) and stands for Sassy CSS. These are extensions of CSS adding powerful rules to the basic language (sort of like a programming language) such as the ability to add variables and functions to manipulate values. You can go here to find out more:SASS
Using
translate3d(25px, 51px, 0)
instead oftranslate(25px, 51px)
cleans up the jaggies a little (Windows), though the baseline is still a little iffy.That’s pretty cool.
Thank you for the tip :)
This is fancy and yes sir,I like it! Ya know what would would make this a schoch fancier is if these attributes would flip automatically with the language direction. One of the benefits of using tables is that they have the magic flip to match the direction. But heck, we have been balancing floats and absolute positions for for directional changes so we could manage this too. I would use this technique.
Inspired by this article and my needs, expressed in my critic above, I fumbled my way to a JavaScript solution (42 lines) , that fits all my needs.
A demo is located here, the sources and a Readme are located at GitHub .
Nice.
Using
transform-origin: left bottom
,display: inline-block
on the span andbox-sizing: border-box
on the div and span means the “magic” numbers can be a lot easier. You just have to nudge it to the right, the width of the column.hi
if table direction => rtl , change this css
thank you
It really nice workout for small mobile devices. Using space efficiently.
Hi I want the table header to be set as you did it in the example .But when i checked ur code it does not works for me.And also i want the slanted values in the footer position also for mapping the values. please help