Sideways Headers

Avatar of Chris Coyier
Chris Coyier on

DataStax Astra — Open, multi-cloud stack for modern apps

Christian Heilmann had an interesting CSS predicament the other day. The idea was to make header tags rotated 90-degrees and align along the left of a blog of content rather than at the top.

So, like this.

Easy, right?

Should be pretty easy right? Just absolutely position the header in the upper left (so it doesn’t take up any vertical space) and then rotate it from it’s upper left corner 90 degrees with CSS transforms. Yeah… that’s cool, but here’s the problem: a lot more browsers support absolute positioning than support transforms. That’s problematic, because in the case of those browsers, the headers will now be sitting on and obfuscating content.


How I Would Do It: Feature Detection

I think the best way to handle this is to do feature detection with Modernizr. Make a quick custom build that tests for transforms, load it up at the top of the page, and then only apply the absolute positioning and transforms (and other tweaks) when you are in a browser that can deal with it.

And so…

The complete CSS:

aside {
    position: relative;  

aside h3 {
    background: #369;
    color: #fff;
    padding: 5px 10px;
    margin: 0 0 10px 0;

/* Class name via Modernizr */
.csstransforms aside {
    border-left: 34px solid #369;
    /* Make a little room */
    padding-left: 10px;
.csstransforms aside h3 {

    /* Abs positioning makes it not take up vert space */ 
    position: absolute;
    top: 0;
    left: 0;
    /* Border is the new background */
    background: none;
    /* Rotate from top left corner (not default) */
    -webkit-transform-origin: 0 0;
    -moz-transform-origin:    0 0;
    -ms-transform-origin:     0 0;
    -o-transform-origin:      0 0;
    -webkit-transform: rotate(90deg); 
    -moz-transform:    rotate(90deg); 
    -ms-transform:     rotate(90deg); 
    -o-transform:      rotate(90deg); 

View Demo   Download Files

The weakness left in this technique is that if the header is longer than the space available, it doesn’t push down the aside’s height to compensate. There really just isn’t a way to do that with just CSS (you can’t set the height of something to match the width of something, basically). For the record, you could use JavaScript to do it.

Can we do it without Modernizr?

Christian et al. didn’t want to use Modernizr (for reasons I can’t possibly comprehend ;). Lennart Schoors, in the comments of his post, came up with this technique, where the paragraph elements themselves were also transformed (moved). By default, there is a bunch of empty space at the top of the aside, and the transform moves them back up to fill that space. Without transforms, the gap is still there, making room for the absolutely positioned header. Pretty smart!

The one shortcoming I can see is that it targets paragraph elements specifically. In a real environment you might not be able to count on that, so you are either writing a selector to cover all possible elements to move, or using an non-semantic wrapper. Also, this is subject to the same weakness as I described about header length above.

Improvements welcome!