WeasyPrint icon indicating copy to clipboard operation
WeasyPrint copied to clipboard

Table with "float:right" duplicates at the start of a page

Open juanjo-nan opened this issue 2 years ago • 2 comments

(Tested in 54.3 and 57.2) If we create a document where we have a page jump and a table with "float:right" attribute at the start of the page, part of this table duplicates (in this case, the table with the red border): image If we delete the "float:right" form the table, the table works correctly: image

Here is the html code i use for this example:

<html>
    <style>
        @page {
            size: A4;
            @top-left {
                content: "";
            }
            @top-right {
                content: "";
            }
            @bottom-right-corner {
                content: counter(page) " / " counter(pages);
                text-align: right;
                font-family: 'Arial';
                bottom:0;
                font-size: 9px;
                padding-right: 0.5cm;
                padding-bottom: 0.5cm;
                text-align: right;
                vertical-align: bottom;
            }
        } 
        @media print {
            * {
                -webkit-print-color-adjust: exact !important; /*Chrome, Safari */
                color-adjust: exact !important; /*Firefox*/
            }
            size: A4;
        }
        body {
            font-family: 'Arial';
            font-size: 10px;
          }
    </style>
    <header>
        <table>
            <tr>
                <td>HEADER TABLE 1</td>
                <td>HEADER TABLE 2</td>
            </tr>
            <tr>
                <td>HEADER TABLE 3</td>
                <td>HEADER TABLE 4</td>
            </tr>
        </table>
    </header>
    <body>
        <!-- Text to force the jump page -->
        <table>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
            <tr>
                <td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
                <td>Etiam ullamcorper augue fringilla elit posuere interdum.</td>
                <td>Nullam quis magna tristique, commodo magna a, vulputate dolor.</td>
                <td>Vivamus quis felis eget ante hendrerit ornare.</td>
            </tr>
        </table>
        <table>
            <tr>
                <td>
                    <table style="border: 1px solid black;">
                        <tr>
                            <td>TABLE 1</td>
                            <td>TABLE 1</td>
                            <td>TABLE 1</td>
                        </tr>
                        <tr>
                            <td>TABLE 1</td>
                            <td>TABLE 1</td>
                            <td>TABLE 1</td>
                        </tr>
                        <tr>
                            <td>TABLE 1</td>
                            <td>TABLE 1</td>
                            <td>TABLE 1</td>
                        </tr>
                    </table>
                </td>
                <td>
                    <table style="float:right;border: 1px solid red;">
                        <tr>
                            <td>1 ROW | 1 COLUMN</td>
                            <td>1 ROW | 2 COLUMN</td>
                        </tr>
                        <tr>
                            <td>2 ROW | 1 COLUMN</td>
                            <td>2 ROW | 2 COLUMN</td>
                        </tr>
                    </table>
                </td>
            </tr>
        </table>
    </body>
</html>

juanjo-nan avatar Jan 17 '23 13:01 juanjo-nan

I have been exploring the cause of this issue. I haven't yet worked out what the best solution to it is, but I think I'm on the right track. Apologies for the long post, as there's a few different aspects to this issue.

As observed in the original ticket, it seems that this issue appeared in v54. As such, I've been comparing the differences to how v53.4 handles it to v54.

A few things that I found interesting when playing around while rendering in v54, with HTML based off the HTML provided in the original description.

Here is the rendering of a 12 row table without float. image 12 rows without float, rendered in v54

You will see here that the table goes over multiple pages, with rows numbered 8 to 12 (inclusive) going across to the new page.

Here's the same HTML rendered, but with a float: right added to the table. image 12 rows with float, rendered in v54

What I found very interesting was that in all my testing, the part that's repeated is the section that would be rendered on the second page if the table wasn't a float. In this example, rows numbered 8 to 12.

So that got me thinking, what would happen if we had a table that spanned over 2 page breaks, instead of just 1 page break. I made a table with 80 rows.

Here's is the rendering of an 80 row table without float. image 80 rows without float, rendered in v54

Here's the same HTML rendered, but with a float: right added to the table. image 80 rows with float, rendered in v54

As I had thought might happen, mayhem ensues. All of the table is rendered on one page (page 2). There is no page 3.

So the issue has to do with handling continuing the table when it goes over multiple pages, or where Weasyprint thinks it goes over multiple pages. So with the 12 row example, without the float, the table is spread across 2 pages. Whilst the float causes the beginning of the table to be pushed to the new page, there seems to be a bug where Weasyprint thinks that it goes over multiple pages.

I've pinpointed the handling of this to be this logic that appears to have been added in in v54: https://github.com/Kozea/WeasyPrint/blob/v54.0/weasyprint/layout/page.py#L569-L588

If for example, you were to take the if statement that checks if a box is a float, and just not do anything, you don't get the original bug. In my testing, I just did:

        if box.is_floated():
            continue

and the original bug no longer happens.

However, this would likely mean that there's no multi-page support for tables that are floated.

Which brings me back to v53.4, and how it handles multi page support for tables. The long story short is, that it doesn't. Here's a screenshot of the 80 row floating table from v53.4:

image 80 rows with float, rendered in v53.4

There is no page after this. The table just goes off the page.

So it seems that this issue was introduced when solving https://github.com/Kozea/WeasyPrint/issues/36. Which is why, whilst it's easy to fix this issue by not supporting page breaks, I'm not really sure what the ultimate fix is. We can't just revert back to disallowing page breaks in floats, as that is a valid use case, and I assume that there are situations where this code is behaving as expected.

joshhendo avatar Apr 17 '24 11:04 joshhendo

A bit of further investigation to find out how it gets into the broken_out_of_flow property on context.

It looks to be this code https://github.com/Kozea/WeasyPrint/blob/v54.0/weasyprint/layout/block.py#L615-L623 which causes the float table to be added to the broken_out_of_flow list. The reason for this is because, looking at https://github.com/Kozea/WeasyPrint/blob/v54.0/weasyprint/formatting_structure/boxes.py#L291-L295 a floated box isn't considered the normal flow. As a test, I removed the is_floated check from this is_in_normal_flow, and rendering seemed to work fine, even over multiple pages.

I'm not suggesting this as the fix, as I am not experienced enough in the WeasyPrint codebase to fully understand why is_floated is returned here, and what the side effects would be of removing it (it could break many other scenarios).

joshhendo avatar Apr 17 '24 11:04 joshhendo