Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

toebes.com - Print preview issues #139133

Closed
toebes opened this issue Jul 13, 2024 — with webcompat-app · 12 comments
Closed

toebes.com - Print preview issues #139133

toebes opened this issue Jul 13, 2024 — with webcompat-app · 12 comments
Labels
browser-firefox engine-gecko The browser uses the Gecko rendering engine
Milestone

Comments

@toebes
Copy link

toebes commented Jul 13, 2024

URL: https://toebes.com/codebusters/Samples/firefox_toebes_printing_example.html

Browser / Version: Firefox 128.0
Operating System: Windows 10
Tested Another Browser: Yes Chrome

Problem type: Something else
Description: Printing doesn't format correctly
Steps to Reproduce:
This is an extract of a sample case of the set of tools for Science Olympiad Code Busters (https://toebes.com/codebusters/) that generate and print tests.

When we print the tests using other browsers (Chrome, Edge) we are able to get consistent formatting and output such that the page fits on the sheet of paper and text is rendered cleanly. However, in the past year or so we have received complaints from Firefox users that it doesn't format and print well.

I have run through the W3c validator to ensure that the HTML is valid.

If you load the file in Firefox and then print, you will notice several issues:

  1. Firefox generates 5 pages instead of the 3 that it should.
  2. The names of participants table ends up wider than the page.
  3. The Score table on the first page is off the right hand edge of the page.
  4. The header for the second page (Page 1) is on a page by itself
  5. The footer for the second page (Page 1) is near the top of the third page
  6. The text for the timed question appears too high on the page
  7. The text for the timed question is in a slightly larger font such that it wraps early.
  8. Similar problems are on the last page, with the header appearing nominally in the correct place
  9. The footer for the last page is on a page by itself.

Note that I have experimented with multiple options for the print scale and margins, for purposes of comparison I set the margins to .5" all around and forced the scale to 100% in all three browsers.

I've uploaded an image showing a side by side comparison of the rendered first page.

View the screenshot Screenshot
Browser Configuration
  • None

From webcompat.com with ❤️

@webcompat-bot webcompat-bot added this to the needstriage milestone Jul 13, 2024
@webcompat-bot webcompat-bot added browser-firefox engine-gecko The browser uses the Gecko rendering engine labels Jul 13, 2024
@toebes
Copy link
Author

toebes commented Jul 13, 2024

If you need me to generate a smaller example showing individual problems, don't hesitate to ask.

@softvision-raul-bucata softvision-raul-bucata changed the title toebes.com - see bug description toebes.com - Print preview issues Jul 15, 2024
@softvision-raul-bucata
Copy link

softvision-raul-bucata commented Jul 15, 2024

Thanks for the report. I was able to reproduce in Firefox Nightly, and Firefox Release.

Reproducible issues are moved to our Bugzilla component; please see: https://bugzilla.mozilla.org/show_bug.cgi?id=1907822

Closing as moved.

[qa_29/2024]

@dholbert
Copy link

dholbert commented Sep 6, 2024

Hi @toebes - I'm only seeing one difference (aside from font subtleties) between Firefox and Chrome, and it's a case where Firefox is honoring a forced pagebreak that the content is requesting, and Chrome is ignoring it (near the top of page 2).

I'm not entirely sure which behavior is correct -- I filed https://bugzilla.mozilla.org/show_bug.cgi?id=1917145 on it with a reduced testcase -- but in the meantime I think you can avoid that difference by removing pagebreak from this element in your testcase:

                    <div class="question pagebreak">

With that addressed, I'm not seeing any other substantial differences. Would you mind retesting and seeing if you're still seeing differences between Firefox and Chrome? And if you are, maybe share PDFs and/or screenshots to highlight the issues? Thanks!

@toebes
Copy link
Author

toebes commented Sep 6, 2024

Remember that this is a reduced case. I didn't want to burden you with the 20 page version.

Removing the pagebreak breaks lots of cases and is there to ensure that everything is paginated correctly. In theory the pagebreak should be innocuous when you are already at the start of a page.

To show the differences, I generated this from your test case: here's the Firefox version which ends up as 5 pages and if you look at the first page, the table is cut off to the right.
Firefox-Bug.pdf

Here's the Chrome version which is only 3 pages (as expected).
Chrome-OK.pdf

Please let me know what else I can provide. If you want to see the extreme case you can go to:

toebes.com/codebusters/TestManage.html?importURL=Samples/NC_C_Regional_1_2024.json
Then click on Test Packet and then the Print button. It should be a 20 page document with the first page not being numbered and all subsequent pages numbered 1-19. With Firefox you get 26 pages with the last page numbered as Page 12.

@dholbert
Copy link

dholbert commented Sep 6, 2024

Remember that this is a reduced case. I didn't want to burden you with the 20 page version.

Removing the pagebreak breaks lots of cases and is there to ensure that everything is paginated correctly.

Sure -- I wasn't suggesting you remove all requested pagebreaks. :) Let me go into a bit more detail about why that one is troublesome...

In this particular case, the testcase is essentially requesting two pagebreaks in a row. Specifically, right now the content on the original reduced testcase looks like this:

<div class="page">
  <div class="head">2024 Science Olympiad National Codebusters Division B</div>
  <div class="headright">Team Number:_B_________</div>
  <div class="foot">Page 1</div>
  <div class="question pagebreak">

And here, both the page and question pagebreak elements have page-break-before:always:

            .page {
[...]
                page-break-before: always;
[...]
            }
[...]
            .pagebreak {
                page-break-before: always;
            }

This means the content is essentially requesting a page-break before each of those elements. That's why the first bit of content (notably the head/headright) end on on one new page, and then the question itself ends up on another page, in Firefox and Safari at least.

I think technically Chrome is correct because the second forced-pagebreak here is supposed to be propagated to its parent since it's the first child (or the first non-abspos child, at least), which means the parent is essentially requesting two pagebreaks at the exact same spot (once explicitly, one propagated from the child), which results in a single break. At some point Firefox and Safari will implement those page-break propagation rules (maybe in this Firefox bug -- forced page-breaks in Firefox are a bit hairy and are something we'd like to rework, but we probably won't get to it in the next few months at least).

In the meantime, if you're looking for ways to work around this issue, you might try avoiding this sort of "double-page-break-request" where the content has two page-break-before:always elements in a row and is relying on the browser to coalesce them into a single pagebreak.

Hopefully that makes sense and might be workable, if you're interested in ideas for workarounds. Thanks again for the bug report!

@dholbert
Copy link

dholbert commented Sep 6, 2024

To show the differences, I generated this from your test case: here's the Firefox version which ends up as 5 pages and if you look at the first page, the table is cut off to the right. Firefox-Bug.pdf

Thanks for sharing this -- so for me, in order to get that "cut-off-on-the-right" issue (and in order to get a 5th page), I have to activate a non-default setting -- I have to choose "Scale: 100%" in the Firefox print dialog** (in the "More Settings" expandable section).

Could you check if you have that setting toggled? If so -- I'll bet things improve for you with the "Scale: Fit to Page Width", as shown here:
image
(that's the default setting, in both Firefox and Chrome -- "Fit to Page Width" in Firefox, and "Scale:Default" in Chrome.)

@dholbert
Copy link

dholbert commented Sep 6, 2024

If you want to see the extreme case you can go to:

toebes.com/codebusters/TestManage.html?importURL=Samples/NC_C_Regional_1_2024.json Then click on Test Packet and then the Print button. It should be a 20 page document with the first page not being numbered and all subsequent pages numbered 1-19. With Firefox you get 26 pages with the last page numbered as Page 12.

Thanks. So, good news -- analyzing that extreme case, I can get Firefox to match Chrome with fairly-minimal workarounds. Details:

  • So first, to clarify -- in Chrome, that document actually gives me a 13-page print-preview & PDF (not 20), with the first page not being numbered and the final page being numbered 12. (I suspect that's what you meant to say, rather than 20-page-document etc. - I'm guessing those counts came from a different page that you were also considering linking here.)

  • In Firefox, I get 25 pages (with lots of blanks pages), not quite 26 -- I only get 26 pages (the count you mentioned) if I choose the non-default "Scale: 100%" setting per my previous comment. With the default "fit to page width", I only get 25 pages of output.

  • And if I add the following styles to avoid redundant pagebreak-requests, then Firefox only gives me 13 pages of output, and they exactly match the output that Chrome gives, to my eye (aside from minor font differences).

.page > .pagebreak { break-before: initial !important; }
.page { break-after: initial !important; }

Here's the Chrome output that I get from this document:
chrome.pdf

Here's the output that I get with Firefox with the above two CSS styles added to the stylesheet (to override some of the styles that are otherwise requesting double-pagebreaks that Firefox doesn't currently coalesce together):
firefox-with-workaround-css.pdf

@dholbert
Copy link

dholbert commented Sep 6, 2024

(side note: given that "Scale: Fit to Page Width" and "Scale: 100%" produce different results, that's actually a good clue that the page here is using some explicitly-sized content that's wider than the available space on the page. That's why stuff gets clipped when you ask for 100% scale, and why it gets scaled down to avoid clipping when you use the default "Fit to Page Width".

Specifically looking at the clipped elements on the first page in the reduced testcase, we have this for the "nameline" (the section where "Team numb[...]" gets clipped):

table.nameline {
[...]
  width: 50rem;

And we have this defining the size of the scoring table below that (note that there are 5 th elements, so we've got 5*11 = 55rem).

        table.testscores th {
[...]
            width: 11rem;
        }

1rem is 16px here, so 50rem is 50*16px = 800px and 55rem is 55*16px = 880px here.

And in Firefox at least, 800px is slightly wider than the available width on a US Letter page with 0.5in-wide margins. Here's a testcase to visualize this: data:text/html,<div style="width:800px; height: 100px; border: 5px solid black; box-sizing: border-box">

Chrome has an interesting behavior where they seem to force "fit to page width" even if you try to choose a large scale factor. But if you try reducing the scale factor, you can see that ~92% scale is where 800px exactly fills the page area (with default margins), and they seem to refuse to scale up beyond that (including to 100%) even if you ask them to.

@dholbert
Copy link

dholbert commented Sep 6, 2024

So, bottom line, this is my diagnosis of what's going on:

  • the extra pages here are mostly coming from bug 1772396 where Firefox [and Safari apparently] aren't properly propagating/coalescing redundant-pagebreak-requests. This is a bug but can be worked around by trying to avoid putting two page-break requests back-to-back on consecutive elements (break-after followed by break-before, or break-before on parent + child).
  • Additionally: for users who have selected the non-default "scale: 100%" option in the print dialog "more settings" section, there may be additional clipping and overflow-onto-a-few-extra-pages, due to the content using explicit sizes that turn out to be slightly wider than the available page area (per previous comment). This is arguably a bit of a bug in the content (asking for more width than we have available), though fortunately browser defaults help here. (Though unfortunately the "scale" setting is sticky, so if a user has activated that setting in the past, they'd hit this in this case.)

@dholbert
Copy link

dholbert commented Sep 6, 2024

@toebes I hope the above helps, particularly my notes with good news on the extreme case. Let me know if you have further questions about what's going on here; otherwise I'm hopeful that it's not too tricky to work around this in the meantime (e.g. using CSS similar to my [...]: initial !important rules quoted above -- or rather removing the CSS declarations that those ones are stomping on), should you choose to do so.

@toebes
Copy link
Author

toebes commented Sep 7, 2024

Some great observations! Thank you.

I've fixed the width issues on that score table (thank you for pointing that out) and it works "better" as long as they specify scale to width. Scale to 100% still doesn't behave as expected (you can see the page number on the subsequent page). I hope to get that pushed out to production after a bit more testing.

One thing that I did want to point out is that the .page style has a page-break-inside: avoid; which might have some bearing on bug 1772396 being applied to this case.

  .page {
       page-break-inside: avoid;
       padding: 0.5in 0in 0.25in 0in !important;
       position: relative;
       width: 100%;
       height: 100%;
       page-break-after: always;
       page-break-before: always;
   }

@dholbert
Copy link

dholbert commented Sep 8, 2024

it works "better" as long as they specify scale to width. Scale to 100% still doesn't behave as expected

That's good news, though if you're still seeing a difference between those configurations in Firefox, then that's an indication that you've still got some element with too large of a specified width to actually fit on the page. If everything is fitting horizontally, then "Fit to Page Width" and "scale: 100%" would produce exactly the same layout.

(Note: Chrome has a bug in these scale settings, meaning their "scale:100%" layout can't be relied on -- so if you're seeing good results from them with scale:100%, don't trust it too much -- it might not remain good after they fix that bug. :) )

you can see the page number on the subsequent page

That indicates that your positioning for these page numbers is too large for them to fit in the available space on the page. (You happen to be getting lucky that "fit to page width" is having to scale stuff down, such that it happens to scale the heights enough to make stuff fit vertically too.)

Looking at your original testcase, I can see that this is trivially happening with the "Page 2" text that you mentioned was being pushed to its own page when printed at 100% scale.

Here's the relevant CSS from your testcase:

  @page {
    margin: 0.5cm;
  }
  .page .foot {
    height: 0.25in;
[...]
    position: absolute;
[...]
    top: 10.5in;
}
.page .foot {
  margin: 0.7em auto;

Those various offsets are placing the .foot element beyond the bottom of the printable area on the page, which is why the text overflows onto another page.

Specifically, for a US Letter sheet of paper:

  • The paper is 11 inches tall.
  • After subtracting your specified margin: 0.5cm from the top and bottom (1cm total), we're left with roughly 10.6in of printable space on the page. (1cm = 0.4in, roughly, so we've got 11in - 0.4in = 10.6in.)
  • The first .page .foot CSS-rule quoted above asks for the top edge of .foot to be 10.5in from the top edge of its page's printable area. That would put its top edge almost exactly at the bottom of the printable area (0.1in away). This is already too far down for the text to entirely fit. But that's also not the last offset we have to account for -- it moves down a bit further to account for the final CSS that I quoted above, margin: 0.7em (which pushes that element further downwards by roughly 2/3 the height of a line of text, which is almost certainly beyond that 0.1in -- i.e. fully off the page).
  • So with all of that combined, we find that the text won't fit in the available space on that page, so it gets pushed to the next one.

To avoid that overflowing page number, you need to use smaller top value there -- 10.5 is too tall and (when combined with the margins) is basically pushing that text off the page. (You might find things are more robust if you use bottom-based indexing -- but that requires your .page elements to be sized to precisely fill the actual page, which might lead to further rabbit-holes/whack-a-moles.)

One thing that I did want to point out is that the .page style has a page-break-inside: avoid;

Yup, I saw that -- that turns out not to be relevant here. Quoting the spec, "...a forced break value effectively overrides any avoid break value that also applies at that break point." https://drafts.csswg.org/css-break-3/#forced-breaks

("page-break-inside: avoid" also can't save you in cases where the content is simply positioned at too far of an explicit offset to be able to fit on the same page, as is the case with the .page .foot CSS discussed above in this comment. :) In that situation, a page-break is unavoidable, unless there are additional scale factors coming into play.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
browser-firefox engine-gecko The browser uses the Gecko rendering engine
Projects
None yet
Development

No branches or pull requests

4 participants