corymathews
corymathews

Reputation: 12619

CSS3 Transform Alignment Issues Inside a Table

I am trying to achieve a table which has text rotated -90degrees. Up until now I have been using images of the text, however I was hoping to change this over to text.

CSS3 rotated text within a table

There are a few problems I cannot seem to fix.

  1. Column 07 text overflows onto column 08.
    • I cannot fix this with overflow:hidden; because I have to set the width and height both to 200px to get the correct shape.
  2. I have to set the width and height of the rotated text which does not make it very flexible to work with, and this also causes problem number 1.
  3. I have to set the margin to "0 -100px" because I have to set the width to 200px but once rotated its width is still 200px, which would make the table incredible large.
  4. If the font size is changed it no longer fits in the columns nicely.
  5. The fonts look terrible, and are hard to read. I figure this will work itself out in future updates of the browsers.

Here is a jsFiddle of it in action

http://jsfiddle.net/CoryMathews/ZWBHS/

I need it to work and have gotten it to the same point in IE7+, Chrome, FF, and Opera.

Any ideas on how to improve this method making it actually usable? Some of my ideas are:

  1. I could calculate the widths, height, etc with some javascript on page load, this would solve problems 2 and 3 above but not 1. However I hate to rely on javascript for display.

  2. Perhaps I am misusing the transform-origin that would give me better control. The number I am currently using "0 0" allows me to easily calculate the needed sizes.

Upvotes: 8

Views: 3835

Answers (4)

approxiblue
approxiblue

Reputation: 7122

This solution fixes some of your problems, but it's not perfect:

  1. Use whitespace: nowrap to disable text flowing to the next line.
  2. Wrap the contents of each cell in a container with width: 1em. Columns are always wide enough for 1 line of vertical text. You can freely adjust the font size.
  3. Manually set the height of the table to fully display the rotated content (by -90 degrees). Hard-coding heights is not great, but there are advantages: no need for fixed widths and negative margins to counter the fixed widths / transform origins / relative positioning / JavaScript; text automatically snaps to bottom of column.

  4. See 2.

  5. Sans-serif fonts are recommended. The less detailed the fonts, the better they look after transforms.

This works in Firefox, Chrome, Opera, IE9+. Vertical text does not work on IE8 and earlier. I tried rotating the table using:

filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3)

and the result looks horrible, so I added fallback style to display a simple horizontal table.

body {
    font-family: sans-serif;
    padding: 10px;
    font-size: 12px;
}

td, tr, th, table { border: 1px solid #333; }
td:nth-child(odd) { background: #eee; }
td {
    overflow: hidden;
    white-space: nowrap; /* text on one line only */
    vertical-align: bottom;
    height: 300px; /* to be adjusted: column is not always tall enough for text */
}

td > div {
    padding: 10px;
    width: 1em; /* column is always wide enough for text */
}

td > div > div {
    -moz-transform: rotate(-90deg);
    -o-transform: rotate(-90deg);
    -webkit-transform: rotate(-90deg);
    -ms-transform: rotate(-90deg) !important;
    transform: rotate(-90deg);
}
<!--[if LT IE 9]>
    <style>
        table { width: 100px; }
        td {
            white-space: normal;
            vertical-align: baseline;
            height: auto;
        }
        td > div {
            width: auto;
        }
    </style>
<![endif]-->
<table>
    <tr>
        <th>01</th>
        <th>02</th>
        <th>03</th>
        <th>04</th>
        <th>05</th>
        <th>06</th>
        <th>07</th>
        <th>08</th>
        <th>09</th>
        <th>10</th>
        <th>11</th>
        <th>12</th>
    </tr>
    <tr>
        <td><div><div>Report Results 1</div></div></td>
        <td><div><div>Shinanigans</div></div></td>
        <td><div><div>CSS Transforms Suck</div></div></td>
        <td><div><div>Lorem Ipsum</div></div></td>
        <td><div><div>So Damn Pixelated</div></div></td>
        <td><div><div>This font looks Terrible</div></div></td>
        <td><div><div>Too Long to read on 1 line Set dimensions suck</div></div></td>
        <td><div><div>Grumble Grumble.</div></div></td>
        <td><div><div>Homebrew!</div></div></td>
        <td><div><div>Spotify Commercial Suck</div></div></td>
        <td><div><div>Grooveshark FTW!</div></div></td>
        <td><div><div>Beer time yet?</div></div></td>
    </tr>
</table>

Upvotes: 6

Oleg
Oleg

Reputation: 24988

First let's fix overlapping text: td{white-space:nowrap;}

CSS transformations are somewhat similar to "position:relative" in one aspect, they modify the rendering of an object rather than its position in the flow. This means there is currently no way to dynamically adjust the cell height based on the div width (at least until css expressions start being implemented).

With that finding in mind, we now are free to take the div out of flow all we want. I'm gonna go and set it absolutely to top left corner of the parent cell. Being a trained professional, I'm allowed to do this: td{position:relative;} td>div{position:absolute;top:0;left:0;}

Well look at this, now the entire content of the cell has been shifted way up. We can't just adjust the position of the block as it will affect the way it's transformed; instead we'll adjust block displacement: margin:100% 0 -100%;

We've taken the element out of the flow above (and for a good reason, too), now we'll just apply a height to the parent cell and we're good to go:

http://jsfiddle.net/ZWBHS/2/

Update:

You could always add text-overflow property and fix the text&cell size so that it requires minimum work updating like http://jsfiddle.net/ZWBHS/3/

So that truncated text is not lost, maybe throw in a title attribute duplicating it?

Upvotes: 1

killofki
killofki

Reputation: 11

as Duopixel , (unrotate)

<style>

body { font-family: "Times New Roman", Times, serif; padding:10px; }
td, tr, th, table { border:1px solid #333; }
td:nth-child(odd) { background:#eee; } /* No IE, No Cares */

td.title { width:200px; }

table {       
    -moz-transform: rotate(-90deg);
    -o-transform: rotate(-90deg);
    -webkit-transform: rotate(-90deg);
    -ms-transform: rotate(-90deg) !important;
    transform: rotate(-90deg);
    -webkit-transform-origin:0 0;
    -moz-transform-origin:0 0;
    -ms-transform-origin:0 0;
    -o-transform-origin:0 0;
    transform-origin:0 0;
    background-color:transparent;

    width:250px; 

    position:relative;
    top:250px;
  }

td > div {       
    -moz-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    -webkit-transform: rotate(90deg);
    -ms-transform: rotate(90deg) !important;
    transform: rotate(90deg);
    -webkit-transform-origin:0 0;
    -moz-transform-origin:0 0;
    -ms-transform-origin:0 0;
    -o-transform-origin:0 0;
    transform-origin:0 0;
    background-color:transparent;

    position:relative; /*Needed to position in the correct columns*/
    height:20px; /* Need to not set this, needed for columns to fill*/
    left:20px; /*Needed to line up, .5 of width - padding*/
}

</style>

<!--[if LT IE 9]>
    <style>
        table {
            filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
            top:0px;
        }
        td div { /* ah..? didn't action of filter..? by td > div..? */
            filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
            overflow:hidden;
            width:20px; /* fix to number.. */
            height:20px; /* fix to number.. */
        }
    </style>
<![endif]-->
<table>
    <tr>
        <td class=title >Report Results 1</td>
        <td><div>01</div></td>
    </tr>
    <tr>
        <td class=title >Shinanigans</td>
        <td><div>02</div></td>
    </tr>
    <tr>
        <td class=title >CSS Transforms Suck</td>
        <td><div>03</div></td>
    </tr>
    <tr>
        <td class=title >Lorem Ipsum</td>
        <td><div>04</div></td>
    </tr>
    <tr>
        <td class=title >So Damn Pixelated</td>
        <td><div>05</div></td>
    </tr>
    <tr>
        <td class=title >This font looks Terrible</td>
        <td><div>06</div></td>
    </tr>
    <tr>
        <td class=title >Too Long to read on 1 line Set dimensions suck</td>
        <td><div>07</div></td>
    </tr>
    <tr>
        <td class=title >Grumble Grumble.</td>
        <td><div>08</div></td>
    </tr>
    <tr>
        <td class=title >Homebrew!</td>
        <td><div>09</div></td>
    </tr>
    <tr>
        <td class=title >Spotify Commercial Suck</td>
        <td><div>10</div></td>
    </tr>
    <tr>
        <td class=title >Grooveshark FTW!</td>
        <td><div>11</div></td>
    </tr>
    <tr>
        <td class=title >Beer time yet?</td>
        <td><div>12</div></td>
    </tr>
</table>

Upvotes: 1

methodofaction
methodofaction

Reputation: 72385

Applying transformations on tables makes all browsers go bonkers. I've encountered the multiline problem too and the only workaround I found was to change the table markup so that it's not the div that is rotated, it's the entire table.

You then "unrotate" your table headers with the reverse transformation:

http://jsfiddle.net/G93KE/

I have no idea if this works with IE7-8 filters.

Upvotes: 3

Related Questions