web-dev-qa-db-fra.com

Comment gérer les sauts de page lors de l'impression d'un tableau HTML volumineux

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

Mon problème est la façon dont la table est imprimée sur plusieurs pages. Parfois, il coupe parfois une ligne en deux, ce qui la rend illisible car une moitié se trouve sur le bord saillant de la page et le reste est imprimé en haut de la page suivante.

La seule solution plausible à laquelle je puisse penser est d'utiliser des DIV empilées au lieu d'un tableau et de forcer les sauts de page si nécessaire .. mais avant de passer à travers tout le changement, je pensais pouvoir demander ici auparavant.

252
h3.
<!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>
265
Sinan Ünür

Remarque: lorsque vous utilisez le saut de page après: toujours pour la balise, un saut de page sera créé après le dernier bit du tableau, créant ainsi une page entièrement vierge à la fin! Pour résoudre ce problème, changez-le en page-break-after: auto. Cela casserait correctement et ne créerait pas une page vierge 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>
42
Josh P

Extension de la solution Sinan Ünü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 ne soit pris en compte que pour les éléments de bloc, pas pour la cellule, le tableau, la ligne ni le bloc en ligne.

Si vous essayez de display:block la balise TR, et que vous utilisez page-break-inside:avoid, cela fonctionne, mais vous dérangez avec la disposition de votre tableau.

20
vicenteherrera

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

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

10
MDave

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

7
marcgg

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
Wendel Tavares

J'ai fait face au même problème et je cherchais partout une solution. Enfin, je découvre quelque chose qui convient à tous les navigateurs.

html {
height: 0;
}

utiliser ce css ou au lieu de css, vous pouvez avoir ce javascript

$("html").height(0);

J'espère que cela fonctionnera pour vous aussi.

1
Jay

J'ai fini par suivre l'approche de @ vicenteherrera, avec quelques modifications (qui sont probablement spécifiques à bootstrap 3).

Fondamentalement; nous ne pouvons pas casser trs, ni tds car ils ne sont pas des éléments de niveau bloc. Nous intégrons donc divs dans chacun d’entre eux et appliquons nos règles page-break-* à l’égard de div. Deuxièmement; nous ajoutons un peu de remplissage 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 introduite (à mon avis - par bootstrap). Je ne suis pas sûr de présenter une nouvelle solution à partir des autres réponses à cette question, mais je pense que cela aidera peut-être quelqu'un.

1
Aaron

J'ai vérifié de nombreuses solutions et tout le monde ne fonctionnait pas bien.

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

tfoot with 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 recouvert par le contenu du tableau.

tfoot avec seulement: display: table-footer-group; ne se chevauche pas, mais ne se trouve 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>

Une réserve place sur les dernières pages, la deuxième place dans votre pied de page.

0
Zenon K.