Search code examples
htmlcssgoogle-chromeuser-interfaceprinting

How to prevent an empty gap appearing in elements when printed?


I have below a minimal webpage that prints as two green pages with a blue box centered on each page.

This is accomplished by creating two green divs that are the size of the page, and each div contains a blue div that is positioned 50% from the top-left corner and then is translated -50% back, a common centering technique.

body {
  /* red */
  background-color: #ffb7b7;
  margin: 0;
}

div.page {
  /* green */
  background-color: #a2ffb5;
  border-radius: 1in;
  width: 11in;
  height: 8in;
  overflow: hidden;
  position: relative;
}

div.box {
  /* light blue */
  background-color: #e2e5ff;
  /* dark blue */
  border: 7pt solid #7e89ff;
  border-radius: 1in;
  width: 5in;
  height: 5in;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

@media print {
  @page {
    margin: 0;
    size: landscape;
  }
  div.page {
    break-before: page;
    break-inside: avoid;
    page-break-inside: avoid;
    width: 100vw;
    height: 100vh;
  }
  div.box {
    break-inside: avoid;
    page-break-inside: avoid;
  }
}
<div class="page">
  <div class="box"></div>
</div>
<div class="page">
  <div class="box"></div>
</div>

This looks fine when viewed as a webpage:

screenshot of webpage

But when printed, a strange empty gap suddenly appears in the middle of the first blue box:

screenshot of print preview

This isn't just a bug with the print preview; the gap actually appears in the printed page or PDF. The issue oddly never affects the last page.

I tried using break-inside: avoid and page-break-inside: avoid, but to no avail. How can I prevent gaps from appearing in printed elements?


Solution

  • This appears to be a bug in Chrome that is triggered when an element falls below the bottom of a non-last printed page and then translate() is used to move it back up.

    In this particular example, we can work around the issue by using an alternative centering technique. For example, change these lines:

    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    

    to this instead:

    right: 50%;
    bottom: 50%;
    transform: translate(50%, 50%);
    

    Chrome seems to work fine when elements fall of the top, left, or right edges of the page; the bug only occurs of the bottom edge. I'm not aware of any general solution that works in all scenarios.