How to Handle Page Breaks when Printing a Large HTML Table

Solution with the CSS break-inside property

Read our snippet if you need to print an HTML table with many rows over multiple pages.

Please note that in order to examine the results more efficiently, you need to create an "index.html" file in your local machine and try out the codes locally to see the results better. You also need to press "CTRL + P" if you use Windows or "CMD + P" if using Mac to see the results on the print page.

Example of handling page breaks when printing a large table:

<!DOCTYPE html>
<html>
  <head>
    <style>
      @media print {
        table {
          page-break-inside: avoid;
        }
        thead {
          display: table-header-group;
        }
      }
    </style>
  </head>
  <body>
    <table>
      <thead>
        <tr>
          <th>Column 1</th>
          <th>Column 2</th>
          <th>Column 3</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Row 1, Column 1</td>
          <td>Row 1, Column 2</td>
          <td>Row 1, Column 3</td>
        </tr>
        <!-- more rows... -->
      </tbody>
    </table>
  </body>
</html>

The @media print rule specifies print-specific styles that will be applied when the <table> is printed. Within this rule, we set page-break-inside: avoid; on the table element to prevent the table from being split across pages. This property tells the browser to try to keep the entire table on one page, rather than breaking it up. Note that this property is not supported in all browsers, so you may need to experiment with other approaches if you encounter issues.

We also set display: table-header-group; on the thead element. This ensures that the table header (the tr containing the column headings) is repeated on each page, which makes it easier to understand the content on each page of the printed table.

The rest of the HTML is a basic table with a header row (thead) and a body (tbody) containing multiple rows (tr) of data. Note that this example doesn't include any specific page breaks within the table, as it assumes the table will fit on a single page.

Page breaks can sometimes be tricky to handle, and there may be some variations in behavior across different browsers. It's always a good idea to test your code on multiple browsers and adjust as needed. If you're encountering issues with page breaks in a specific browser, you can try using different CSS properties or approaches to achieve the desired result.

Avoiding footer on every page break

To prevent a table footer from being displayed on every page break within the table body, you can add the following CSS rule:

tfoot {
  display: table-footer-group;
}

This will ensure that the table footer is only displayed at the end of the table, rather than on every page break within the table body.

Here's an example:

<!DOCTYPE html>
<html>
  <head>
    <style>
      tfoot {
        display: table-footer-group;
      }
    </style>
  </head>
  <body>
    <table>
      <thead>
        <tr>
          <th>Column 1</th>
          <th>Column 2</th>
          <th>Column 3</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Row 1, Column 1</td>
          <td>Row 1, Column 2</td>
          <td>Row 1, Column 3</td>
        </tr>
        <tr>
          <td>Row 2, Column 1</td>
          <td>Row 2, Column 2</td>
          <td>Row 2, Column 3</td>
        </tr>
        <tr>
          <td>Row 3, Column 1</td>
          <td>Row 3, Column 2</td>
          <td>Row 3, Column 3</td>
        </tr>
        <!-- and so on... -->
      </tbody>
      <tfoot>
        <tr>
          <td>Footer 1</td>
          <td>Footer 2</td>
          <td>Footer 3</td>
        </tr>
      </tfoot>
    </table>
  </body>
</html>

Breaking after a specific row

To break after a specific row, you can use the nth-child selector in combination with the page-break-after property. For example, to break after every 5th row, you can use the following CSS:

tr:nth-child(5n) {
  page-break-after: always;
}

This will force a page break after every 5th row.

Here's an example of how to break a large HTML table into pages after a specific number of rows, in this case 5 rows per page:

<!DOCTYPE html>
<html>
  <head>
    <style>
      @media print {
        table {
          page-break-inside: avoid;
        }
        tr {
          break-inside: avoid;
        }
        tbody {
          display: block;
        }
        tbody tr:nth-child(5n + 1) {
          page-break-before: always;
        }
      }
    </style>
  </head>
  <body>
    <table>
      <thead>
        <tr>
          <th>Column 1</th>
          <th>Column 2</th>
          <th>Column 3</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Row 1, Column 1</td>
          <td>Row 1, Column 2</td>
          <td>Row 1, Column 3</td>
        </tr>
        <tr>
          <td>Row 2, Column 1</td>
          <td>Row 2, Column 2</td>
          <td>Row 2, Column 3</td>
        </tr>
        <tr>
          <td>Row 3, Column 1</td>
          <td>Row 3, Column 2</td>
          <td>Row 3, Column 3</td>
        </tr>
        <tr>
          <td>Row 4, Column 1</td>
          <td>Row 4, Column 2</td>
          <td>Row 4, Column 3</td>
        </tr>
        <tr>
          <td>Row 5, Column 1</td>
          <td>Row 5, Column 2</td>
          <td>Row 5, Column 3</td>
        </tr>
        <tr>
          <td>Row 6, Column 1</td>
          <td>Row 6, Column 2</td>
          <td>Row 6, Column 3</td>
        </tr>
        <tr>
          <td>Row 7, Column 1</td>
          <td>Row 7, Column 2</td>
          <td>Row 7, Column 3</td>
        </tr>
        <!-- and so on... -->
      </tbody>
    </table>
  </body>
</html>

In this example, we're using the @media print rule to apply print-specific styles to the table. We're setting page-break-inside: avoid; on the table to ensure that table rows aren't split across pages, and break-inside: avoid; on the table rows to prevent them from being split. We're also setting display: block; on the table body to ensure that it takes up the full width of the page.

Finally, we're using the nth-child selector to select every 5th row in the table body and applying page-break-before: always; to force a page break before that row. This results in 5 rows per page.

Please note that the page-break-* properties have been updated to break-* in newer versions of browsers. You can use the updated properties for more consistent behavior across different browsers.