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


261

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

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

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


28
По касательной, возможно, стоило бы добавить <thead>к вашей таблице следующий css, thead {display: table-header-group; }чтобы напечатать заголовок таблицы на всех последующих страницах (полезно для более длинных таблиц данных).
Дэвид говорит восстановить Монику

Ответы:


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>

18
Это также терпит неудачу в браузерах WebKit (например, Safari и Chrome)
Майкл Харен

5
Хотя это совместимый со стандартами способ сделать это, единственным браузером, который в настоящее время реализует стандарт, является Opera. Обратите внимание, что это является частью css2, и поэтому отсутствие реализации, вероятно, будет проблемой в течение некоторого времени, потому что, очевидно, никто не заботится.
пк

16
Спецификация CSS 2.1 указывает, что атрибуты стиля разрыва страницы применяются только к элементам уровня блока. Режим отображения по умолчанию для строк таблицы - таблица-строка. К сожалению, по умолчанию никакие элементы таблицы не являются элементами блочного уровня, включая саму таблицу.
Исуарес

2
@ SinanÜnür Это не требование, поэтому вы не можете на него полагаться, и, к сожалению, по моим тестам я вижу, что веб-набор видел «может» и игнорировал все, что выходило за его пределы. Странно, но в IE появилась довольно приятная поддержка печати больших таблиц. Никогда не думал, что буду петь свои похвалы в любой момент.
lsuarez

6
Я могу подтвердить, что это не работает нормально в Chrome или любом другом браузере Webkit (например, Safari, Opera) - если только под словом «работает отлично» вы подразумеваете «исключает любые функции, которые считаются необязательными». Я думаю, что большинство людей хотят запускать верхние и нижние колонтитулы, а также таблицы, которые допускают разрывы страниц только между строками, ни одна из которых не реализована в Webkit по состоянию на 2015/11/13.
ДокторДеструкто

47

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

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

Работает для меня в Chrome и является хорошим простым решением CSS.
Райан

1
Я пробую то же решение, но оно не разбивает данные таблицы и не пропадает лишних данных, а не отображает их на следующей странице. Есть догадки?
Нулевой указатель

24

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

<!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, он работает, но мур вокруг с вашей сервировки стола.


2
Вот простой способ динамически добавлять div с помощью jquery:$(document).ready(function(){$("table tbody th, table tbody td").wrapInner("<div></div>");});
Крис Блум

1
Благодаря Синану Урюну, Висентеререре и Крисблуму7. Я применил комбинацию ваших ответов, и теперь это работает!
Нурхак Кая

Вы можете попробовать установить @media CSS на « tr { display: block; }Только для печати», а не добавлять все посторонние <div>элементы. (Не проверял, но стоит посмотреть)
Стивен Р

11

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

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


У вас есть образец, как это применить? Я пытался присвоить мою таблицу className, splitForPrintно в JS нигде не было ссылки на элемент с помощью className splitForPrint. Только часть, где, var splitClassName = 'splitForPrint';но это все.
Compaq LE2202x

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

Для меня это сработало, ни одно из других решений не сработало. +1 Пришлось добавить немного CSS, чтобы получить правильные разрывы .page-break {page-break-after: всегда; }
фуги

Да, добавив .page-break {page-break-after: всегда; } это спасло мой день!
Милодкий

7

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

page-break-after

page-break-before 

Например:

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

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

через


Я не уверен, тебе придется проверить. Если нет, разделите их на разные массивы и разделите массивы пустым div
marcgg

Вы должны будете применить это к строке таблицы или даже к ячейке, но не к таблице, я думаю. Кроме этого, это должно работать.
Пекка

2
не работает в хроме.
Игнорируется так,

5

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

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

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


2

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

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

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

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


1

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

html {
height: 0;
}

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

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

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


0

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

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

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

tfoot with only: 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>

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


-1

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

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

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


-2

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

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-й главе (т.е. исходной голове).


-3

Принятый ответ не работал для меня во всех браузерах, но у меня работал следующий 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;
}

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.