Как справляться с разрывами страниц при печати большой таблицы HTML

У меня есть проект, который требует печати таблицы HTML со многими строками.

Моя проблема заключается в том, как таблица печатается на нескольких страницах. Иногда он вырезает строку пополам, делая ее нечитаемой, потому что одна половина находится на краю страницы, а остальная часть печатается в верхней части следующей страницы.

Единственное правдоподобное решение, о котором я могу думать, - это использовать сложные DIVs вместо таблицы и принудительные разрывы страниц, если это необходимо.. но перед тем как пройти через все изменения, я подумал, что могу спросить здесь раньше.

Ответ 1

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

Ответ 2

Примечание: при использовании разрыва страницы: всегда для тега он создает разрыв страницы после последнего бит таблицы, каждый раз создавая абсолютно пустую страницу! Чтобы исправить это, просто измените его на page-break-after: auto. Он сломается правильно и не создаст лишнюю пустую страницу.

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

Ответ 3

Расширение от решения Синан Юнюр:

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

Кажется, что page-break-inside:avoid в некоторых браузерах учитывается только для элементов блока, а не для ячейки, таблицы, строки или встроенного блока.

Если вы попытаетесь display:block тег TR и используйте там page-break-inside:avoid, это работает, но портится ваш макет таблицы.

Ответ 4

Ни один из ответов здесь не работал у меня в Chrome. AAverin на GitHub создал полезный Javascript для этой цели, и это сработало для меня:

Просто добавьте js к вашему коду и добавьте класс splitForPrint в таблицу, и он аккуратно разделит таблицу на несколько страниц и добавит заголовок таблицы на каждую страницу.

Ответ 5

Используйте эти свойства CSS:

page-break-after

page-break-before 

Например:

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

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

через

Ответ 6

Я недавно решил эту проблему с хорошим решением.

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

Работает как шарм!

Ответ 7

В конце концов я столкнулся с подходом @vicenteherrera, с некоторыми настройками (которые, возможно, связаны с бутстрапом 3).

В принципе; мы не можем сломать tr s или td, потому что они не являются элементами уровня блока. Поэтому мы вставляем div в каждый и применяем наши правила page-break-* к div. Во-вторых, мы добавляем некоторые дополнения к вершине каждого из этих divs, чтобы компенсировать любые артефакты стиля.

<style>
    @media print {
        /* avoid cutting tr 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 content within a div
        // (todo: add logic so we only do this when printing)
        $("table tbody th, table tbody td").wrapInner("<div></div>");
    })
</script>

Коррекция полей и дополнений была необходима, чтобы компенсировать какой-то джиттер, который вводился (по моим предположениям - из бутстрапа). Я не уверен, что я представляю новое решение из других ответов на этот вопрос, но, по-моему, это может помочь кому-то.

Ответ 8

Я проверил множество решений, и никто не работал хорошо.

Итак, я попробовал небольшой трюк, и он работает:

tfoot со стилем: position: fixed; bottom: 0px; помещается внизу последней страницы, но если нижний колонтитул слишком высок, он перекрывается содержимым таблицы.

tfoot только: display: table-footer-group; не перекрывается, но не находится в нижней части последней страницы...

Положим два 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>

Ответ 9

Я сталкивался с одной и той же проблемой и всюду искал решение, наконец-то я нашел то, что работает для меня во всех браузерах.

html {
height: 0;
}

используйте этот CSS или вместо CSS вы можете иметь этот JavaScript

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

Надеюсь, это сработает и для вас.

Ответ 10

Я пробовал все приведенные выше предложения и нашел простое и работающее решение для кросс-браузера для этой проблемы. Для этого решения нет стилей или разрывов страниц. Для решения формат таблицы должен быть следующим:

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

Вышеперечисленный формат и работа в кросс-браузерах

Ответ 11

Ну парни... Большинство решений здесь не сработало. Так вот как все сработало для меня..

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>

Первый набор головок используется как фиктивный, так что не будет отсутствующей верхней границы в 2-й главе (то есть исходной голове) во время разрыва страницы.

Ответ 12

Принятый ответ не работал у меня во всех браузерах, но после этого css работал у меня:

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

Структура html была:

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

В моем случае возникли некоторые дополнительные проблемы с thead tr, но это разрешило исходную проблему с тем, чтобы строки таблицы не ломались.

Из-за проблем с заголовком я в конечном итоге закончил:

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

Это не помешало разрыву строк; только содержимое каждой ячейки.