Kozea / WeasyPrint

The awesome document factory
https://weasyprint.org
BSD 3-Clause "New" or "Revised" License
7.14k stars 682 forks source link

Background image does not cover page margin area #1993

Closed MWedl closed 11 months ago

MWedl commented 11 months ago

When using background-image with background-size: cover; on a @page, the page margin area is not covered. However, when using background-color, the page margin area is covered. The problem might be similar to https://github.com/Kozea/WeasyPrint/issues/1943

<html>

<head>
    <style>
        @page {
            size: A4;
            margin: 3cm;

            background-image: url("https://upload.wikimedia.org/wikipedia/commons/6/6a/PNG_Test.png");
            background-position: center;
            background-size: cover;
            background-repeat: no-repeat;
        }
    </style>
</head>

<body>
    <h1>CONTENT</h1>
</body>

</html>

image

liZe commented 11 months ago

Hi!

I think that there’s no bug in WeasyPrint this time.

background-size: cover defines the size of your image so that it covers the whole box it’s drawn on. The box here is the page without its margins, just as an image that covers a normal box is resized to cover its border box, without its margins.

The image is not clipped, and is actually drawn on the left and right margin boxes (it fits vertically and overflows horizontally). That’s what we expect.

If you want to display the image on the page + margins, you can either:

MWedl commented 11 months ago

Thanks for your suggestions. I still think an @page background-image should also cover its margin area. Most other HTML to PDF rendering tools at https://printcss.live/ cover the whole page background with the image, not just the content area.

CSS Paged Media Module Level 3, 3.1. Page Backgrounds and Painting Order:

In the page model, the page background behaves similar to the root background: its background painting area is the bleed area, which covers the entire page box, including its margins (regardless of background-clip).

liZe commented 11 months ago

Thanks a lot for your detailed answer 😍.

Most other HTML to PDF rendering tools at https://printcss.live/ cover the whole page background with the image, not just the content area.

You’re right, WeasyPrint and PDFReactor position the content according to the page’s padding box, but the other tools use the margin box.

In the page model, the page background behaves similar to the root background: its background painting area is the bleed area, which covers the entire page box, including its margins (regardless of background-clip).

I agree with this sentence: the painting area is the whole page, including the margins. That’s why WeasyPrint paints the page background on the whole page when we set a color or a repeating background image for example.

But there’s more:

Page backgrounds are anchored within the page box’s padding area by default (and honor background-origin […].)

This means that the (0, 0) coordinate is by default the page’s padding area origin, and the padding area doesn’t include the margins. And this position can be changed using background-origin, so you can set a negative page margin offset to draw the image in the page margin for example.

At least that’s what I understand! 😄

Unfortunately, I can’t find any official test for that, so I don’t know what’s "right" here. I’m open to discussion, but I’m not convinced yet!

MWedl commented 11 months ago

Thanks for taking time to investigate the issue :smile: . I fully understand that you do not want to implement something that is ambiguous in the CSS spec and where no tests for the expected behavior exist.

I have re-read the parts of the CSS spec you linked and think you are right about background-origin. You convinced me about that. However, a following sentence states:

However if background-attachment is fixed then the image is positioned relative to the page box including its margins (i.e. the background positioning area is the page’s margin box).

background-attachment: fixed:

The background is fixed with regard to the viewport. In paged media where there is no viewport, a fixed background is fixed with respect to the page box and therefore replicated on every page.

If I understand it correctly, it should be possible to let the background cover the whole page (including its margin area) by settings background-attachment: fixed;. I have tried this solution in WeasyPrint, but the output is the same as in the screenshot above. It seems that WeasyPrint does not correctly handle background-attachment: fixed.

liZe commented 11 months ago

I have tried this solution in WeasyPrint, but the output is the same as in the screenshot above. It seems that WeasyPrint does not correctly handle background-attachment: fixed.

That’s right! Fixing this looks like to be a useful way to provide you a clean solution.

and therefore replicated on every page.

That’s a bit strange, it looks like position: fixed, but I’m not sure that we want to draw the background on every page (for example not on pages that are not targeted by the @page selector the background is defined in.)

MWedl commented 11 months ago

I also think it is meant that background images should only be replicated on every page that the @page rule applies to. This is the most intuitive interpretation for me. It the background was replicated on every page, it would not be possible to set background images on specific pages (e.g. @page:first, named pages, etc.). It would target pages that are outside the scope of the @page selector.

pmjdebruijn commented 11 months ago

One thing to keep in mind is interaction with actual bleed area, as full page images generally should also cover the bleed area.

liZe commented 11 months ago

One thing to keep in mind is interaction with actual bleed area, as full page images generally should also cover the bleed area.

As explained in the specification, with background-attachment: fixed:

the background positioning area is the page’s margin box

So, the origin is not the bleed box, it’s the margin box.

But it’s not a real problem: if you want images to be displayed in the bleed area, it’s possible to use negative values. And that’s actually a good idea: 100% width means 21cm for A4, and if we have bleed areas we have to use something greater to get something drawn on the bleed area.

Once again, the problem is not that the image is not drawn on the margin / bleed area, it’s already possible. The problem is "only" the default origin.

liZe commented 11 months ago

I think that the bug is fixed and tested, feedback is welcome!

MWedl commented 11 months ago

With background-attachment: fixed the background images are positioned as expected and cover the whole page including the margin area. Thanks for implementing it :smile:

akashbit commented 8 months ago

@liZe I think this is not released in 60.2 can you release a new version with this?

liZe commented 8 months ago

@liZe I think this is not released in 60.2 can you release a new version with this?

It’ll be included in version 61.

akashbit commented 8 months ago

@liZe thanks, any idea of the 61 timeline / release date?

liZe commented 8 months ago

any idea of the 61 timeline / release date?

We have a couple of things to fix before releasing, and it may take some time.

If you really want to use this feature, you can install the main branch.

akashbit commented 8 months ago

hi @liZe Thanks for the reply, no pressure but we want to upload a release on our ubuntu server and want a stable product out there. If we buy you coffee for a week, will that motivate you to help us out 😉

grewn0uille commented 8 months ago

Hello @akashbit! If you want to support the development of WeasyPrint, you can become a sponsor on OpenCollective. A new version will be release when it’s ready. We prefer to provide quality rathen than rush a devolopment/release :)