How to print A4 pages using CSS?

Asked

Viewed 16,970 times

6

I currently use the mpdf library for reporting. However, in some reports I need to send more than 400 pdf pages and this ends up taking a long time and consuming many server resources.

I even checked questions related to library performance to try to optimize it, but nothing helped mpdf Slow!

So I decided to create my reports in HTML and CSS, and found some difficulties:

1° I will be dependent on resources (plugins and related) of the browser for printing in pdf.

2° My layout remains well standardized being a header on all pages and a table with information. So I need to know when the information fills the entire A4 sheet to create a new page and repeat the process.

I used Google Chrome’s native PDF save and Cutepdf Writer to send in pdf, but they have differences in display form so my question is:

How to recognize the page boundary?

How to improve compatibility in printing them?

Example of the procedure.

body {
  background: rgb(204, 204, 204);
}
page {
  background: white;
  display: block;
  margin: 0 auto;
  margin-bottom: 0.5cm;
  box-shadow: 0 0 0.5cm rgba(0, 0, 0, 0.5);
}
page[size="A4"] {
  width: 21cm;
  height: 29.7cm;
}
page[size="A4"][layout="portrait"] {
  width: 29.7cm;
  height: 21cm;
}
@media print {
  body,
  page {
    margin: 0;
    box-shadow: 0;
  }
}
.header {
  padding-top: 10px;
  text-align: center;
  border: 2px solid #ddd;
}
table {
  border-collapse: collapse;
  width: 100%;
  font-size: 80%;
}
table th {
  background-color: #4caf50;
  color: white;
  text-align: center;
}
th,
td {
  border: 1px solid #ddd;
  text-align: left;
}
tr:nth-child(even) {
  background-color: #f2f2f2
}
<page size="A4">

  <div class="header">
    [nomeEmpresa]
    <br>[endereco] - [cidade] - [cep]
    <br>[cnpj] - [telefone]
    <br>
    <h3>[nomeRelatorio] -  [tipoRelatorio]</h3>
  </div>

  <table class="table">
    <thead>
      <tr>
        <th>[coluna0]</th>
        <th>[coluna1]</th>
        <th>[coluna2]</th>
        <th>[coluna3]</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>Mark</td>
        <td>Otto</td>
        <td>@mdo</td>
      </tr>
      <tr>
        <td>2</td>
        <td>Jacob</td>
        <td>Thornton</td>
        <td>@fat</td>
      </tr>
      <tr>
        <td>3</td>
        <td>Larry</td>
        <td>the Bird</td>
        <td>@twitter</td>
      </tr>
    </tbody>
  </table>
</page>

<page size="A4"></page>

also in the: jsfiddle

  • What specific difficulty are you having? Supposedly, working with exact measurements, it would only be the case for your application to calculate the division of texts before generating HTML. For free text, it needs a certain ingenuity, which would probably be a bit complex to solve in one question. (in fact this type of problem, in an ideal world, would not be solved with web application, which is naturally inferior to a desktop, but this escapes the scope of the question :P )

  • A possible solution is you see the type of font you will use and "choose" a predetermined number of lines per page. If you use a monospace, the space that the text occupies is perfectly calculable, sacrificing a little of the aesthetic in favor of the predictability of the output. Then the breaks would be managed in the server-side application. In sources not proportional you can do, but you have to give a reasonable margin of error, and have the measurements of the characters on the server for calculation purposes. It’s a bit more work. CSS in theory would have predicted some features, but only "work in theory":) even.

  • @Bacco thought to do this way but some texts presented larger and passed the size, the monospace font could solve this problem?

  • Only with CSS not. It would be the case to use monospace, and count the characters in the server-side application. When you reach a certain amount, close the page and open the next one. If all the lines are shorter than the width is even simpler, just count per line. But if you’re going to have paragraphs, then you need to elaborate better.

2 answers

2

2

You can go to any of the alternatives below. It depends on how accurate you need to be.

Method 1

What I usually do in personal projects and that do not require much precision, is to define the font size in 12pt to the html in my CSS by being worth 100% of the size. I then convert the size of an ordinary A4 sheet of millimeters (210 x 297) for pixels (793 x 1122, approximately). Thus, I define a <div> with the dimensions of the sheet and other <div> to serve as an isolator and place the content: each information may have its font size that will not modify the dimensions of the <div> that would represent the common A4 role (not the A4 craft). Add margin as needed.

I must say that it works for me, mainly with mono-spaced font. See an example:

html { font-size: 12pt; }

.folha { background-color: #ccc; padding: 0.5em; }
.a4_vertical { width: 793px; height: 1122px; }
.a4_horizontal { width: 1122px; height: 793px; }
<div id="folha-a4" class="folha a4_vertical">
   <div id="conteudo">
       Folha A4
   </div>
</div>

Method 2

If you want more precision, I recommend using the CSS paper licensed MIT. To use, basically you need...

... In the <header>

  • Loads the style: <link rel="stylesheet" href="dist/paper.css">
  • Sets the size of the paper: <style>@page { size: A5 }</style>

... In the <body>

  • Add the paper size class (A4)
  • Adds if you want in format landscape (landscape) - portrait is standard
  • Tag (<div>, <section>, et cetera) that will have all the contents of a sheet, add the class sheet. Each leaf is one sheet different!

There are other details that can be learned as needed. There are also several examples on the site. Here’s an adapted:

<link href="https://cdnjs.cloudflare.com/ajax/libs/paper-css/0.3.0/paper.css" rel="stylesheet" />
<style>
  @page {
    size: A4
  }
</style>

<body class="A4">

  <section class="sheet padding-10mm">

    <article>Exemplo de folha A4</article>

  </section>

</body>

It is worth mentioning that it is possible to generate PDF with the Electron-pdf, as the project page informs. I believe I use less resources.

  • I know it’s been a long time, but I’m trying to use this answer solution, and it works, but not at first, I used it to open a file in A4 sheet format, however first it appears with html occupying the space in 100% and only after tinkering with the page, click or thing like that it updates and goes to A4 form. You know what it could be?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.