I have a big table with lots of columns that I need to fit into a PDF page using DOMPDF. Just like here, my headers are much wider than the corresponding content, so I'm trying to rotate them. The HTML opened in Firefox seems ok, but the resulting PDF is not.
The Setup
HTML:
<td class="cell rotated_vertical_td" style="width:3%;">
<div class="rotated_vertical">Rotated_</div>
</td>
The width attribute above is being calculated in PHP based on the total number of columns.
CSS:
.cell {
font-size: 8pt;
}
.rotated_vertical_td {
height: 280px;
width: 20px;
text-transform:uppercase;
margin:0;
padding:0;
}
.rotated_vertical {
-webkit-transform:rotate(270deg);
-moz-transform:rotate(270deg);
-ms-transform:rotate(270deg);
-o-transform:rotate(270deg);
transform:rotate(270deg);
transform-origin: 50%;
width: 20px;
}
I had to apply the .cell
class to each <td>
because DOMPDF was not picking up the table td
rule for some reason.
The Problem
It seems like DOMPDF first renders the text, changes the table cell accordingly, and then rotates it. Which means that the column still takes as much space and that breaks the whole point.
I've tried using substr()
to cut the text to be only 2, 4 or 8 characters long. Looks like the column widths are adjusting accordingly.
Those are the screenshots of the actual PDF being rendered. As you can see, the last one fits less columns, even though the markup and the CSS is the same. Only thing thats changed is the characters count. Looks like it completely ignores the width I set on those headers.
In case of HTML, it looks like that width: 20px;
on the inner div makes a difference - if I remove it, the HTML headers become wide as well.
So again, it looks like the inner div width stretches the table header cells. I can override that width and it works for HTML, but it does not for PDF.
What makes it worse is that DOMPDF does not seem to support having multiple page orientations in a single document so I can't have that page in the landscape mode.
In an answer to this question it is advised to use the absolute positioning, but I am not sure how that'd work with DOMPDF. For example, they treat the position:fixed
elements as page headers, might have something reserved for the absolute positioned ones.
Please help
Update 2015-01-26
Thanks to BrianS for his help, I've managed to make the text rotate using the CSS approach he suggested and the latest DOMPDF downloaded from GitHub. Before that, I was generating the dynamic images with rotated text for each one of the headers.
Several things I'd like to point out for those who got here searching for the solution (including the future me I guess)
Positioning the content is a nightmare. There seems to be no way to predictably control the position and behaviour of the rotated headers neither in Firefox, nor in DOMPDF, and that is frustrating. First I had to change the
transform-origin
property to be:transform-origin: left bottom 0;
... just so it's position is less random because otherwise changing either
top
/left
orwidth
/height
properties kept moving the block in both dimensions. The fact that there are about 7 variables to control (top
,left
,width
/height
of the:after
element, as well as theline-height
andwidth
/height
of the wrapping cells) makes it impossible to go through all possible combinations of those to get the desirable position.If a header is too long and contains any breakable characters - such as spaces - it gets split into several lines and those lines get combined into one by overlaying each other. Please see:
I couldn't find a way to prevent that. Seeing that the text that doesn't contain any breakable characters is still being placed on one line,
- tried playing with the width/height/line-height controls
- tried replacing the spaces with
inside of the csscontent
property but that gets printed directly and does not act as the non-breakable space - tried using the ASCII characters as advised here but it outputs some weird characters instead
- replaced the spaces with underscores - it works but looks ugly
- so I've tried replacing the spaces with
<span style="color:#fff">_</span>
so this way the color of the underscore matches the background, but again, that whole thing gets printed directly, and I've also realised that that span would break the line anyway - it feels like that line that gets combined just doesn't have enough width, but if I change the width of the
.rotate .content:after
element, it just moves that overlayed line to the right, although when I open the HTML in Firefox that seems to help
So for now, my solution is using the underscores, but that doesn't look professional. I'd appreciate if you could help me out with a soution.
Here's the updated setup:
HTML:
<tr class="table_summary_thead">
<td class="rotated_vertical_td" style="width:3%;">
<a hred="appendix_item_44">
<div class="rotated_vertical_outer">
<div class="rotated_vertical_inner rtb1f73b0b57649457abd0ca2e0e8c94e0f7d79c25">
</div>
</div>
</a>
<style type="text/css">
.rtb1f73b0b57649457abd0ca2e0e8c94e0f7d79c25:after {
content:"COMPREHENSIVE";
}
</style>
</td>
</tr>
CSS:
.table_summary {
width:100% !important;
}
.table_summary td {
text-align:center;
}
.table_summary tbody td {
font-size: 10pt;
padding: 4px;
}
.rotated_vertical_td {
width: 20px !important;
height: 680px !important;
font-size: 8pt;
margin:0;
padding:0;
text-align:left;
}
.table_summary_thead {
line-height: 220px;
text-align:left;
}
.rotated_vertical_outer {
position: relative;
overflow: visible;
text-align:left;
}
.rotated_vertical_inner:after {
height: 150px;
overflow: visible;
position: absolute;
text-align: left;
transform: rotate(270deg);
transform-origin: left bottom 0;
width: 20px;
top: 100px;
left: 110px;
}
Including most of the CSS here because who knows, some small part that seems irrelevant might make a difference.