100% height block with vertical text

css, css-transforms, html, vertical-text

Solution

I believe you were only using a `<table>` because it seemed to be the easiest way to achieve what you were looking for, so I cut it out of the equation and used semantic HTML instead. If there was another reason, I apologize in advance and you should be able to port the styles over to use a `<table>` instead.

See the jsFiddle demo to view the code in action. Or, continue on to the code:

HTML

<section class="wrapper">
    <header><h1>Test</h1></header>
    <article>Text.</article><!--
    --><article>More text.</article><!--
    --><article>Photos of cats.</article><!--
    --><article>More photos of cats.</article>
</section>

CSS

.wrapper {
    margin:1em;
    position:relative;
    padding-left:2em; /* line-height of .wrapper div:first-child span */
    background:#fed;
}
.wrapper header {
    display:block;
    position:absolute;
    top:0;
    left:0;
    bottom:0;
    width:2em; /* line-height of .wrapper div:first-child span */
    overflow:hidden;
    white-space:nowrap;
}
.wrapper header h1 {
    -moz-transform-origin:0 50%;
    -moz-transform:rotate(-90deg) translate(-50%, 50%);
    -webkit-transform-origin:0 50%;
    -webkit-transform:rotate(-90deg) translate(-50%, 50%);
    -o-transform-origin:0 50%;
    -o-transform:rotate(-90deg) translate(-50%, 50%);
    -ms-transform-origin:0 50%;
    -ms-transform:rotate(-90deg) translate(-50%, 50%);
    transform-origin:0 50%;
    transform:rotate(-90deg) translate(-50%, 50%);
    position:absolute;
    top:0;
    bottom:0;
    height:2em; /* line-height of .wrapper div:first-child span */
    margin:auto;
    font-weight:bold;
    font-size:1em;
    line-height:2em; /* Copy to other locations */
}
.wrapper article {
    display:inline-block;
    width:25%;
    padding:1em 1em 1em 0;
    vertical-align:middle;
    -moz-box-sizing:border-box;
    -webkit-box-sizing:border-box;
    -ms-box-sizing:border-box;
    -o-box-sizing:border-box;
    box-sizing:border-box;
}

How it works

The `<header>` is set to the height of `.wrapper` and has it's `width` set to `2em` (value of `line-height` for the `<h1>`). Then, the `<h1>` is vertically aligned (with `top:0;bottom:0;height:2em;margin:auto;` [`2em` is also from `line-height`]). Once the `<h1>` is vertically aligned, it is rotated counter-clockwise 90 degrees by the middle of its left side. In order to make the `<h1>` visible again, it is translated `50%` vertically (to pull it back onto the screen horizontally) and `-50%` horizontally (to vertically align it). And yes, the wording is correct--everything just gets confusing once you rotate by [-]90 degrees ;)

Gotchas

- Only a static "height" is supported for the `<h1>`. In this case, only 1 line is supported.

- Wrapping will not work (I've actually disabled it in this example), so anything that doesn't fit in the `height` of `.wrapper` will be hidden.

Problem

I have a block of a variable height in which I want to put another block with 100% height and vertical text (bottom-to-top direction) and stack it to the left side of the outer block. Is there a way to achieve it with CSS transforms but without width and height calculations in JS? This is what I could get so far: ``` <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <style type="text/css"> .block1 { border: 4px solid #888; height: 120px; width: 200px; } .block2 { height: 100%; border: 4px solid red; } .msg { display: inline-block; white-space: nowrap; font-family: Verdana; font-size: 14pt; -moz-transform: rotate(-90deg); -moz-transform-origin: center center; -webkit-transform: rotate(-90deg); -webkit-transform-origin: center center; -ms-transform: rotate(-90deg); -ms-transform-origin: center center; } </style> </head> <body> <div class="block1"> <table class="block2"> <tr> <td> <div class="msg">Hi there!</div> </td> </tr> </table> </div> </body> </html> ``` You can see that the inner block's computed width is the same as the text width before rotation. UPDATE: Here is the picture of what I want to get in the end: It's a horizontal stripe with items stacked to its left side, and with a vertical header block. Stripe's height is variable, so items should adapt and the header's text should remain centered.

Original source