Umgang mit Seitenumbrüchen beim Drucken einer großen HTML-Tabelle

261

Ich habe ein Projekt, bei dem eine HTML-Tabelle mit vielen Zeilen gedruckt werden muss.

Mein Problem ist die Art und Weise, wie die Tabelle über mehrere Seiten gedruckt wird. Manchmal wird eine Reihe in zwei Hälften geschnitten, sodass sie nicht mehr lesbar ist, da sich eine Hälfte am blutenden Rand einer Seite befindet und der Rest oben auf der nächsten Seite gedruckt wird.

Die einzige plausible Lösung, die ich mir vorstellen kann, ist die Verwendung gestapelter DIVs anstelle einer Tabelle und das Erzwingen von Seitenumbrüchen, falls erforderlich. Bevor ich jedoch die gesamte Änderung durchlief, dachte ich, ich könnte hier vorher nachfragen.

h3.
quelle
28
Bei einer Tangente kann es sich lohnen <thead>, Ihrer Tabelle eine mit dem folgenden CSS hinzuzufügen thead {display: table-header-group; }, um den Tabellenkopf auf allen nachfolgenden Seiten zu drucken (nützlich für lange Datentabellen).
David sagt, Monica

Antworten:

277
<!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>
Sinan Ünür
quelle
18
Dies schlägt auch in WebKit-Browsern (z. B. Safari und Chrome) fehl
Michael Haren
5
Während dies die standardkonforme Methode ist, ist Opera der einzige Browser, der den Standard derzeit implementiert. Beachten Sie, dass dies Teil von CSS2 ist und daher die fehlende Implementierung wahrscheinlich für einige Zeit ein Problem sein wird, da sich anscheinend niemand darum kümmert.
pkh
16
Die CSS 2.1-Spezifikation gibt an, dass Seitenumbruchstilattribute nur auf Elemente auf Blockebene angewendet werden. Der Standardanzeigemodus für Tabellenzeilen ist Tabellenzeile. Leider sind standardmäßig keine Tabellenelemente Elemente auf Blockebene, einschließlich der Tabelle selbst.
lsuarez
2
@ SinanÜnür Es ist keine Anforderung, daher kann man sich nicht darauf verlassen, und leider kann ich anhand meiner Tests erkennen, dass das Webkit "Mai" sah und alles darüber hinaus ignorierte. Seltsamerweise hat der IE eine ziemlich gute Unterstützung für das Drucken großer Tabellen. Ich hätte nie gedacht, dass ich in einem bestimmten Punkt sein Lob singen würde.
lsuarez
6
Ich kann bestätigen, dass dies in Chrome oder einem anderen Webkit-Browser (z. B. Safari, Opera) NICHT einwandfrei funktioniert - es sei denn, mit "funktioniert einwandfrei" meinen Sie "schließt alle Funktionen aus, die als optional gelten". Ich denke, die meisten Leute wollen Kopf- und Fußzeilen und Tabellen, die nur Seitenumbrüche zwischen Zeilen zulassen, von denen keine ab dem 13.11.2015 in Webkit implementiert ist.
DoctorDestructo
47

Hinweis: Wenn Sie das Seitenumbruch-Nach verwenden: Immer für das Tag wird nach dem letzten Bit der Tabelle ein Seitenumbruch erstellt, wobei jedes Mal am Ende eine vollständig leere Seite erstellt wird! Um dies zu beheben, ändern Sie es einfach in Seitenumbruch nach: auto. Es wird korrekt unterbrochen und es wird keine zusätzliche leere Seite erstellt.

<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>
Josh P.
quelle
Funktioniert für mich in Chrome und ist eine schöne einfache CSS-Lösung.
Ryan
1
Ich versuche dieselbe Lösung, aber sie bricht keine Tabellendaten und verschwindet zusätzliche Daten, anstatt sie auf der nächsten Seite anzuzeigen. Irgendwelche Ideen?
Nullzeiger
24

Erweiterung von Sinan Ünür Lösung:

<!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>

Es scheint, dass page-break-inside:avoid in einigen Browsern nur Blockelemente berücksichtigt werden, nicht Zellen, Tabellen, Zeilen und Inline-Blöcke.

Wenn Sie versuchen, display:blockdas TRTag zu verwenden und es dort zu verwenden page-break-inside:avoid, funktioniert es, aber es spielt mit Ihrem Tabellenlayout herum.

Vicenteherrera
quelle
2
Hier ist eine einfache Möglichkeit, die Divs dynamisch mit jquery hinzuzufügen:$(document).ready(function(){$("table tbody th, table tbody td").wrapInner("<div></div>");});
Chris Bloom
1
Danke an sinan ürün, vicenteherrera und Chrisbloom7. Ich habe die Kombination Ihrer Antworten angewendet und es funktioniert jetzt!
Nurhak Kaya
Sie können versuchen, das @ media-CSS auf tr { display: block; }Nur Drucken zu setzen, anstatt alle externen <div>Elemente hinzuzufügen . (Nicht getestet, aber einen Blick wert)
Stephen R
11

Keine der Antworten hier hat bei mir in Chrome funktioniert. AAverin auf GitHub hat zu diesem Zweck einige nützliche Javascript erstellt das für mich funktioniert hat:

Fügen Sie einfach das js zu Ihrem Code hinzu und fügen Sie der Klasse die Klasse 'splitForPrint' hinzu. Dadurch wird die Tabelle ordentlich in mehrere Seiten aufgeteilt und jeder Seite wird der Tabellenkopf hinzugefügt.

MDave
quelle
Haben Sie ein Beispiel, wie Sie dies anwenden können? Ich habe versucht, meine Tabelle className als zuzuweisen, splitForPrintaber in der JS wurde nirgends die Referenz des Elements mit dem className verwendet splitForPrint. Nur der Teil wo var splitClassName = 'splitForPrint';aber das war's.
Compaq LE2202x
Abgestimmt, weil das Skript, mit dem Sie verlinkt haben, das Problem des OP nicht ohne nennenswerte Auswahl und Neukonfiguration löst und Sie keine Beispiele dafür angegeben haben, wie man es machen könnte.
Chris Bloom
Hat für mich wie ein Zauber funktioniert, keine der anderen Lösungen hat funktioniert. +1 Musste ein wenig CSS hinzufügen, um die richtigen Unterbrechungen zu erhalten .Seitenumbruch {Seitenumbruch nach: immer; }
fhugas
Ja, indem Sie .page-break {page-break-after: always hinzufügen; } es hat meinen Tag gerettet!
milodky
7

Verwenden Sie diese CSS-Eigenschaften:

page-break-after

page-break-before 

Zum Beispiel:

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

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

über

marcgg
quelle
Ich bin mir nicht sicher, du musst es überprüfen. Wenn nicht, teilen Sie es in verschiedene Arrays auf und trennen Sie die Arrays durch ein leeres div
marcgg
Sie müssen es auf die Tabellenzeile oder sogar die Zelle anwenden, aber nicht auf die Tabelle, denke ich. Davon abgesehen sollte es funktionieren.
Pekka
2
funktioniert nicht in Chrom. Wird ignoriert, als ob 13.06.2012 bei Anwendung auf TR
Ladieu
5

Ich habe dieses Problem kürzlich mit einer guten Lösung gelöst.

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();
}

Klappt wunderbar!

Wendel Tavares
quelle
2

Am Ende folgte ich dem Ansatz von @ vicenteherrera mit einigen Verbesserungen (die möglicherweise Bootstrap 3-spezifisch sind).

Grundsätzlich; Wir können trs oder tds nicht brechen , weil sie keine Elemente auf Blockebene sind. Also binden wir divs in jedes ein und wenden unsere page-break-*Regeln gegen das an div. Zweitens; Wir fügen oben an jedem dieser Divs eine Polsterung hinzu, um eventuelle Styling-Artefakte auszugleichen.

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

Die Rand- und Polsteranpassungen waren notwendig, um eine Art von Jitter auszugleichen, der eingeführt wurde (meiner Vermutung nach - vom Bootstrap). Ich bin mir nicht sicher, ob ich eine neue Lösung aus den anderen Antworten auf diese Frage vorstelle, aber ich denke, dass dies vielleicht jemandem helfen wird.

Aaron
quelle
1

Ich hatte das gleiche Problem und suchte überall nach einer Lösung. Endlich habe ich etwas gefunden, das für jeden Browser für mich funktioniert.

html {
height: 0;
}

Verwenden Sie dieses CSS oder Anstelle von CSS können Sie dieses Javascript verwenden

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

Hoffe, dass dies auch für Sie funktioniert.

Jay
quelle
0

Ich habe viele Lösungen überprüft und niemand hat gut funktioniert.

Also habe ich einen kleinen Trick ausprobiert und es funktioniert:

Fuß mit Stil: Wird position: fixed; bottom: 0px; am Ende der letzten Seite platziert, aber wenn die Fußzeile zu hoch ist, wird sie vom Inhalt der Tabelle überlappt.

tfoot with only: display: table-footer-group; Überlappt sich nicht, befindet sich aber nicht am Ende der letzten Seite ...

Lassen Sie uns zwei Fuß setzen:

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>

Einer reserviert Platz auf nicht letzten Seiten, der zweite setzt in Ihre aktuelle Fußzeile.

Zenon K.
quelle
-1

Ich habe alle oben genannten Vorschläge ausprobiert und eine einfache und funktionierende Cross-Browser-Lösung für dieses Problem gefunden. Für diese Lösung sind keine Stile oder Seitenumbrüche erforderlich. Für die Lösung sollte das Format der Tabelle wie folgt lauten:

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

Das oben genannte Format wurde getestet und funktioniert in Cross-Browsern

Ananth Doss
quelle
-2

Nun Leute ... Die meisten Lösungen hier oben haben nicht funktioniert. So funktionierten die Dinge für mich.

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>

Der erste Satz Kopf wird als Dummy-Satz verwendet, damit beim Seitenumbruch im zweiten Kopf (dh im Originalkopf) kein oberer Rand fehlt.

Aneesh
quelle
-3

Die akzeptierte Antwort funktionierte nicht in allen Browsern für mich, aber das folgende CSS funktionierte für mich:

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

Die HTML-Struktur war:

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

In meinem Fall gab es einige zusätzliche Probleme mit dem thead tr, aber dies löste das ursprüngliche Problem, dass die Tabellenzeilen nicht beschädigt wurden.

Aufgrund der Header-Probleme kam ich letztendlich zu:

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

Dies verhinderte nicht, dass Zeilen unterbrochen wurden. nur der Inhalt jeder Zelle.

David Moeller
quelle