Positioned content is applied starting with page 2 instead of the start of the document
Original author: eclecticgeek (May 15, 2012 04:22:47)
What steps will reproduce the problem? Create an absolutely-positioned or a fixed-positioned element in a document that will not be encountered during the rendering process until after a page break occurs (e.g. at the end of a long document).
What is the expected output? What do you see instead? Expect to see the positioned content appear relative to the first page of the document, but instead it only appears starting with the page in which it was encountered and the pages after that page.
Possible solution: relocate positioned content to the top of a document prior to rendering.
Original issue: http://code.google.com/p/dompdf/issues/detail?id=485
I can confirm the behavior you're reporting, and can also confirm that relocating the positioned content so that it appears on the first "page" is a successful workaround (at least in my case with a fixed position header and footer).
Here's a quick code sample to confirm the issue:
$dompdf = new Dompdf();
$html = '';
$html .= '<div style="position:relative">';
for ($i=0; $i<1000; $i++)
{
$html .= 'Lorem ipsum ';
}
$html .= '</div>';
$html .= '<div style="position:fixed; left:20mm; top:20mm; width:100mm; height:10mm; background:red"></div>';
$dompdf->loadHtml($html);
$dompdf->render();
$dompdf->stream('dom.pdf');
This shows two issues:
- The red banner appears only on page 2 and 3.
- On page 2, the banner lies underneath the text, on page 3 atop of it.
Workaround for both: Move the fixed <div> above the for loop.
This is due to how fixed-position elements are collected for rendering, the assumption appearing to be that they would be declared on the first page.
Looking at this again and the resolution is perhaps easier than I was thinking. All fixed-position elements are collected before rendering begins, but the collection logic doesn't remove them from the document flow and the insertion logic only runs starting with page 2. The collection logic needs to remove those elements from the document flow since not doing so will cause them to render more than once if they naturally occur on pages after the first. Then we can update the insertion logic to run regardless of page.