Comment gérer les sauts de page lors de l'impression d'une grande table HTML

J'ai un projet qui nécessite l'impression d'une table HTML avec plusieurs lignes.

Mon problème est la façon dont la table est imprimée sur plusieurs pages. Il va parfois couper une ligne en deux, ce qui rend illisible parce que la moitié est sur le bord de saignement d'une page et le reste est imprimé sur le haut de la page suivante.

La seule solution plausible à laquelle je peux penser est d'utiliser des DIVs empilés au lieu d'une table et de forcer les sauts de page si nécessaire.. mais avant de passer par tout le changement Je je pensais que je pourrais demander ici avant.

236
demandé sur Jeremy W 2009-11-19 17:24:30

11 réponses

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test</title>
<style type="text/css">
    table { page-break-inside:auto }
    tr    { page-break-inside:avoid; page-break-after:auto }
    thead { display:table-header-group }
    tfoot { display:table-footer-group }
</style>
</head>
<body>
    <table>
        <thead>
            <tr><th>heading</th></tr>
        </thead>
        <tfoot>
            <tr><td>notes</td></tr>
        </tfoot>
        <tbody>
        <tr>
            <td>x</td>
        </tr>
        <tr>
            <td>x</td>
        </tr>
        <!-- 500 more rows -->
        <tr>
            <td>x</td>
        </tr>
    </tbody>
    </table>
</body>
</html>
240
répondu Sinan Ünür 2016-04-27 14:25:49

Note: lors de l'utilisation de la page-break-after: toujours pour la balise, il va créer un saut de page après le dernier bit de la table, créant une page entièrement vierge à la fin à chaque fois! Pour résoudre ce problème, il suffit de le changer en page-break-after: auto. Il se cassera correctement et ne créera pas une page blanche supplémentaire.

<html>
<head>
<style>
@media print
{
  table { page-break-after:auto }
  tr    { page-break-inside:avoid; page-break-after:auto }
  td    { page-break-inside:avoid; page-break-after:auto }
  thead { display:table-header-group }
  tfoot { display:table-footer-group }
}
</style>
</head>

<body>
....
</body>
</html>
39
répondu Josh P 2011-10-14 05:07:46

Expansion à partir de la solution Sinan üür:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test</title>
<style type="text/css">
    table { page-break-inside:auto }
    div   { page-break-inside:avoid; } /* This is the key */
    thead { display:table-header-group }
    tfoot { display:table-footer-group }
</style>
</head>
<body>
    <table>
        <thead>
            <tr><th>heading</th></tr>
        </thead>
        <tfoot>
            <tr><td>notes</td></tr>
        </tfoot>
        <tr>
            <td><div>Long<br />cell<br />should'nt<br />be<br />cut</div></td>
        </tr>
        <tr>
            <td><div>Long<br />cell<br />should'nt<br />be<br />cut</div></td>
        </tr>
        <!-- 500 more rows -->
        <tr>
            <td>x</td>
        </tr>
    </tbody>
    </table>
</body>
</html>

Il semble que page-break-inside: avoid dans certains navigateurs n'est pris en considération que pour les éléments de bloc, pas pour cell, table, row ni inline-block.

Si vous essayez d'afficher: bloquer la balise TR, et Y utiliser page-break-inside: avoid, cela fonctionne, mais gâche avec votre disposition de table.

18
répondu vicenteherrera 2013-09-11 14:03:43

Aucune des réponses ici n'a fonctionné pour moi dans Chrome. AAverin sur GitHub a créé Un Javascript utile à cet effet et cela a fonctionné pour moi:

Ajoutez simplement le js à votre code et ajoutez la classe 'splitForPrint' à votre table et elle divisera soigneusement la table en plusieurs pages et ajoutera l'en-tête de table à chaque page.

9
répondu MDave 2017-01-31 07:52:22

Utilisez ces propriétés CSS:

page-break-after

page-break-before 

Par exemple:

<html>
<head>
<style>
@media print
{
table {page-break-after:always}
}
</style>
</head>

<body>
....
</body>
</html>

Via

6
répondu marcgg 2012-08-13 20:32:39

J'ai récemment résolu ce problème avec une bonne solution.

Css:

.avoidBreak { 
    border: 2px solid;
    page-break-inside:avoid;
}

Js:

function Print(){
    $(".tableToPrint td, .tableToPrint th").each(function(){ $(this).css("width",  $(this).width() + "px")  });
    $(".tableToPrint tr").wrap("<div class='avoidBreak'></div>");
    window.print();
}

Fonctionne comme un charme!

4
répondu Wendel Tavares 2015-06-30 15:25:53

J'ai fini par suivre l'approche de @vicenteherrera, avec quelques réglages (qui sont peut-être spécifiques à bootstrap 3).

Fondamentalement; nous ne pouvons pas casser tr S, ou td S parce qu'ils ne sont pas des éléments de niveau bloc. Donc, nous intégrons div s dans chacun, et appliquons nos règles page-break-* contre les div. Deuxièmement; nous ajoutons un peu de rembourrage au sommet de chacune de ces divs, pour compenser les artefacts de style.

<style>
    @media print {
        /* avoid cutting tr's in half */
        th div, td div {
            margin-top:-8px;
            padding-top:8px;
            page-break-inside:avoid;
        }
    }
</style>
<script>
    $(document).ready(function(){
        // Wrap each tr and td's content within a div
        // (todo: add logic so we only do this when printing)
        $("table tbody th, table tbody td").wrapInner("<div></div>");
    })
</script>

Les ajustements de marge et de remplissage étaient nécessaires pour compenser une sorte de gigue qui a été introduit (par ma conjecture - de bootstrap). Je ne suis pas sûr de présenter une nouvelle solution à partir des autres réponses à cette question, mais je me dis que cela aidera peut-être quelqu'un.

1
répondu Aaron 2016-06-22 17:15:32

J'ai vérifié beaucoup de solutions et n'importe qui ne fonctionnait pas bien.

J'ai donc essayé un petit truc et ça marche:

Tfoot avec style: position: fixed; bottom: 0px; est placé au bas de la dernière page, mais si le pied de page est trop haut, il est chevauché par le contenu de la table.

Tfoot avec seulement: display: table-footer-group; n'est pas chevauché, mais n'est pas au bas de la dernière page...

Mettons deux tfoot:

TFOOT.placer {
  display: table-footer-group;
  height: 130px;
}

TFOOT.contenter {
  display: table-footer-group;
  position: fixed;
  bottom: 0px;	
  height: 130px;
}
<TFOOT  class='placer'> 
  <TR>
    <TD>
      <!--  empty here
-->
    </TD>
  </TR>
</TFOOT>	
<TFOOT  class='contenter'> 
  <TR>
    <TD>
      your long text or high image here
    </TD>
  </TR>
</TFOOT>

On se réserve une place sur les pages non-dernières, la seconde place dans votre accual le pied de page.

0
répondu Zenon K. 2016-12-09 08:01:03

J'ai essayé toutes les suggestions données ci-dessus et trouvé une solution cross browser simple et fonctionnelle pour ce problème. Il n'y a aucun style ou saut de page nécessaire pour cette solution. Pour la solution, le format de la table doit être comme:

<table>
    <thead>  <!-- there should be <thead> tag-->
        <td>Heading</td> <!--//inside <thead> should be <td> it should not be <th>-->
    </thead>
    <tbody><!---<tbody>also must-->
        <tr>
            <td>data</td>
        </tr>
        <!--100 more rows-->
    </tbody>
</table>

Format ci-dessus testé et fonctionnant dans les navigateurs croisés

-1
répondu Ananth Doss 2017-03-13 07:33:41

Eh Bien Les Gars... La plupart des Solutions ici n'ont pas fonctionné. Donc, c'est comment les choses fonctionnent pour moi..

HTML

<table>
  <thead>
   <tr>
     <th style="border:none;height:26px;"></th>
     <th style="border:none;height:26px;"></th>
     .
     .
   </tr>
   <tr>
     <th style="border:1px solid black">ABC</th>
     <th style="border:1px solid black">ABC</th>
     .
     .
   <tr>
  </thead>
<tbody>

    //YOUR CODE

</tbody>
</table>

Le premier ensemble de tête est utilisé comme un mannequin afin qu'il n'y ait pas de bordure supérieure manquante dans la 2ème tête (c'est-à-dire la tête d'origine) pendant le saut de page.

-1
répondu Aneesh 2017-07-06 07:41:53

La réponse acceptée ne fonctionnait pas pour moi dans tous les navigateurs, mais le css suivant fonctionnait pour moi:

tr    
{ 
  display: table-row-group;
  page-break-inside:avoid; 
  page-break-after:auto;
}

La structure html était:

<table>
  <thead>
    <tr></tr>
  </thead>
  <tbody>
    <tr></tr>
    <tr></tr>
    ...
  </tbody>
</table>

Dans mon cas, il y avait quelques problèmes supplémentaires avec le thead tr, mais cela a résolu le problème initial de garder les lignes de la table de se casser.

En raison des problèmes d'en-tête, je me suis finalement retrouvé avec:

#theTable td *
{
  page-break-inside:avoid;
}

Cela n'a pas empêché les lignes de se casser; juste le contenu de chaque cellule.

-3
répondu David Moeller 2015-04-01 19:20:14