openhtmltopdf
openhtmltopdf copied to clipboard
Absolute positioning fails in some common cases
I noticed that absolute positioning has a few annoying defects in the way it deals with vertical lengths:
- anchoring to page bottom: anchoring an element to page bottom makes it leak to next page (obviously, it should stay entirely on the target page, see test cases 2 and 3 here below)
- wrong resolution of relative references to element height: element height in percentage is wrongly resolved (see test case 6 here below)
Test cases
No automated test suite here, just my observations from casual trials (made a bit more systematic to evaluate fringe cases). This is the code chunk used to generate the renderings:try (OutputStream os = new FileOutputStream(new File("absolute.pdf"))) {
try (PdfBoxRenderer renderer = new PdfRendererBuilder().withFile(new File("absolute.html"))
.toStream(os).buildPdfRenderer()) {
renderer.createPDF();
}
}
And this is the source HTML body:
<body>
<div class="element">
1-Some contents to fill<br />-What?<br /> 2-Some contents to
fill<br />-What?<br /> 3-Some contents to fill<br />-What?<br />
4-Some contents to fill<br />-What?<br /> 5-Some contents to
fill<br />-What?<br /> 6-Some contents to fill<br />-What?<br />
7-Some contents to fill<br />-What?<br /> 8-Some contents to
fill<br />-What?<br /> 9-Some contents to fill<br />-What?<br />
10-Some contents to fill<br />-What?<br /> 11-Some contents to
fill<br />-What?<br />
</div>
</body>
NOTE: All the outputs are compared side-by-side with renderings by Chrome/Blink engine (print mode).
1. top-left at page top-left: OK
.element {
position: absolute;
left: 0;
top: 0;
}
2. bottom-left at page bottom-left: FAILED
The element wrongly leaks down to next page. It seems like a limit condition during the placement of last text line tested true despite the height of its containing div was purposely calculated to make enough room for it..element {
position: absolute;
left: 0;
bottom: 0;
}
3. bottom-right at page bottom-right: FAILED
The element wrongly leaks down to next page, same as test case 2..element {
position: absolute;
right: 0;
bottom: 0;
}
4. top-left at page center: OK
The element leaks down to next page as expected..element {
position: absolute;
left: 50%;
top: 50%;
}
absolute_topleft-center.html.txt
5. bottom-right at page center: OK
The element leaks above the page to nowhere as expected..element {
position: absolute;
right: 50%;
bottom: 50%;
}
absolute_bottomright-center.html.txt
absolute_bottomright-center.pdf
6. center at page center (transform): FAILED
Wrong element height calculated for vertical translation (element should move upwards by 50% of its height)..element {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%)
}
7. rotate around center (transform): OK
.element {
position: absolute;
left: 50mm;
top: 50mm;
transform: rotate(-45deg);
}
absolute_rotate-center.html.txt
8. rotate around top-left (transform): OK
.element {
position: absolute;
left: 50mm;
top: 50mm;
transform-origin: 0 0;
transform: rotate(-45deg);
}
absolute_rotate-topleft.html.txt
9. rotate around bottom-right (transform): OK
.element {
position: absolute;
left: 50mm;
top: 50mm;
transform-origin: 100% 100%;
transform: rotate(-45deg);
}
absolute_rotate-bottomright.html.txt
absolute_rotate-bottomright.pdf
10. size relative to page (partial and full): OK
.element {
position: absolute;
left: 0;
top: 0;
width: 50%;
height: 50%;
}
absolute_size-relative.html.txt
.element {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
absolute_size-relative-full.html.txt
I came across the same issue as described in “6. center at page center (transform)”. Here are a few more observations.
- Percentage y component parameters to
translate
seems to be interpreted relative to element width. - Parameters to
translate
(at least the y component) seem to be interpreted as percentage even if absolute values are given.
<!DOCTYPE html>
<html lang="en">
<head>
<style>
@page {
size: 297mm 210mm;
}
.box {
position: relative;
width: 50mm;
height: 50mm;
border: 1pt solid black;
}
.label {
position: absolute;
left: 50%;
top: 50%;
border: 1pt solid red;
line-height: 1.5em;
}
.label.percentage {
transform: translate(-50%, -50%);
}
.label.em-1 {
transform: translate(-50%, -1.5em);
}
.label.em-2 {
transform: translate(-50%, -50em);
}
.label.mm {
transform: translate(-50%, -5mm);
}
</style>
</head>
<body>
<table>
<tr>
<td>
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 50 50">
<path stroke="black" stroke-width=".1pt" d="M 0,0 l 50,50 M 0,50 L 50,0" />
</svg>
<span class="label percentage">Label</span>
</div>
</td>
<td>
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 50 50">
<path stroke="black" stroke-width=".1pt" d="M 0,0 l 50,50 M 0,50 L 50,0" />
</svg>
<span class="label percentage">Long Label</span>
</div>
</td>
<td>
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 50 50">
<path stroke="black" stroke-width=".1pt" d="M 0,0 l 50,50 M 0,50 L 50,0" />
</svg>
<span class="label em-1">Long Label</span>
</div>
</td>
<td>
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 50 50">
<path stroke="black" stroke-width=".1pt" d="M 0,0 l 50,50 M 0,50 L 50,0" />
</svg>
<span class="label em-2">Long Label</span>
</div>
</td>
<td>
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 50 50">
<path stroke="black" stroke-width=".1pt" d="M 0,0 l 50,50 M 0,50 L 50,0" />
</svg>
<span class="label mm">Long Label</span>
</div>
</td>
</tr>
</table>
</body>
</html>
Chrome:
Open HTML to PDF:
Hi All, for the issues with position absolute at the bottom(left-bottom, right-bottom) -> Did you fix them?