Cách xử lý ngắt trang khi in bảng HTML lớn


261

Tôi có một dự án yêu cầu in một bảng HTML có nhiều hàng.

Vấn đề của tôi là cách bảng được in trên nhiều trang. Đôi khi nó sẽ cắt một hàng thành một nửa, làm cho nó không thể đọc được vì một nửa nằm ở cạnh chảy máu của trang và phần còn lại được in trên đầu trang tiếp theo.

Giải pháp hợp lý duy nhất tôi có thể nghĩ đến là sử dụng các DIV xếp chồng thay vì bảng và buộc ngắt trang nếu cần .. nhưng trước khi trải qua toàn bộ thay đổi tôi nghĩ tôi có thể hỏi ở đây trước đây.


28
Trên một tiếp tuyến, có thể đáng để thêm một <thead>vào bảng của bạn với css sau thead {display: table-header-group; }để in tiêu đề bảng trên tất cả các trang tiếp theo (hữu ích cho các bảng dữ liệu loooooong).
David nói phục hồi Monica

Câu trả lời:


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
Điều này cũng thất bại trong các trình duyệt WebKit (ví dụ: Safari và Chrome)
Michael Haren

5
Mặc dù đây là cách tuân thủ tiêu chuẩn để thực hiện việc này, trình duyệt duy nhất hiện đang thực hiện tiêu chuẩn là Opera. Lưu ý rằng đây là một phần của css2, và do đó, việc thiếu triển khai có thể sẽ là một vấn đề trong một thời gian tới, vì rõ ràng không ai quan tâm.
pkh

16
Đặc tả CSS 2.1 chỉ ra rằng các thuộc tính kiểu ngắt trang chỉ được áp dụng cho các thành phần cấp khối. Chế độ hiển thị mặc định cho các hàng của bảng là hàng bảng. Thật không may, theo mặc định, không có phần tử bảng nào là phần tử mức khối, bao gồm cả chính bảng.
lsuarez

2
@ SinanÜnür Đây không phải là một yêu cầu, vì vậy bạn không thể dựa vào nó, và thật không may từ thử nghiệm của tôi, tôi có thể thấy rằng webkit đã thấy "có thể" và bỏ qua bất cứ điều gì ngoài nó. Thật kỳ lạ, IE có một số hỗ trợ in bảng lớn khá đẹp. Không bao giờ nghĩ rằng tôi hát những lời khen ngợi của nó trên bất kỳ điểm nào.
lsuarez

6
Tôi có thể xác nhận rằng điều này KHÔNG hoạt động tốt trong Chrome hoặc bất kỳ trình duyệt Webkit nào khác (ví dụ: Safari, Opera) - trừ khi, "hoạt động tốt", bạn có nghĩa là "loại trừ bất kỳ tính năng nào được coi là tùy chọn". Tôi nghĩ rằng những gì hầu hết mọi người muốn là chạy đầu trang và chân trang và các bảng chỉ cho phép ngắt trang giữa các hàng, không được thực hiện trong Webkit kể từ 2015/11/13.
DoctorDeststallo

47

Lưu ý: khi sử dụng ngắt trang sau: luôn luôn cho thẻ, nó sẽ tạo ngắt trang sau bit cuối cùng của bảng, tạo ra một trang hoàn toàn trống ở cuối mỗi lần! Để khắc phục điều này, chỉ cần thay đổi nó thành ngắt trang sau: tự động. Nó sẽ phá vỡ chính xác và không tạo thêm một trang trống.

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

Hoạt động với tôi trên Chrome và là một giải pháp CSS đơn giản.
Ryan

1
Tôi đang thử cùng một giải pháp, nhưng nó không phá vỡ dữ liệu bảng và biến mất dữ liệu bổ sung thay vì hiển thị nó trên trang tiếp theo. Đoán nào?
Con trỏ Null

24

Mở rộng từ giải pháp 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>

Dường như page-break-inside:avoidtrong một số trình duyệt chỉ được xem xét cho các thành phần khối, không phải cho ô, bảng, hàng không phải là khối nội tuyến.

Nếu bạn cố gắng để display:blockcác TRthẻ, và sử dụng có page-break-inside:avoid, nó hoạt động, nhưng messes xung quanh với cách bố trí bảng.


2
Đây là một cách dễ dàng để thêm các div linh hoạt với jquery:$(document).ready(function(){$("table tbody th, table tbody td").wrapInner("<div></div>");});
Chris Bloom

1
Cảm ơn sinan ürün, Abbeyenteherrera và Chrisbloom7. Tôi đã áp dụng kết hợp các câu trả lời của bạn và bây giờ nó hoạt động!
Nurhak Kaya

Bạn có thể thử đặt CSS @media thành tr { display: block; }Chỉ in, thay vì thêm tất cả các <div>yếu tố không liên quan . (Chưa được thử nghiệm nhưng đáng để xem xét)
Stephen R

11

Không có câu trả lời nào ở đây làm việc cho tôi trong Chrome. AAverin trên GitHub đã tạo ra một số Javascript hữu ích cho mục đích này và điều này hiệu quả với tôi:

Chỉ cần thêm js vào mã của bạn và thêm lớp 'splitForPrint' vào bảng của bạn và nó sẽ chia bảng gọn gàng thành nhiều trang và thêm tiêu đề bảng vào mỗi trang.


Bạn có mẫu về cách áp dụng này? Tôi đã cố gắng gán tên bảng của tôi là splitForPrintnhưng trong JS không có nơi nào tham chiếu phần tử bằng className splitForPrint. Chỉ có một phần var splitClassName = 'splitForPrint';nhưng đó là nó.
Compaq LE2202x

Đã bỏ phiếu vì tập lệnh mà bạn liên kết không giải quyết được vấn đề của OP mà không chọn và cấu hình lại đáng kể, và bạn không cung cấp bất kỳ ví dụ nào về cách người ta có thể thực hiện nó.
Chris Bloom

Làm việc như một cơ duyên đối với tôi, không có giải pháp nào khác hiệu quả. +1 Phải thêm một chút css để có được các khoảng nghỉ chính xác .page-break {page-break-after: always; }
fhugas

Đúng bằng cách thêm .page-break {page-break-after: always; } nó đã cứu ngày của tôi!
milodky

7

Sử dụng các thuộc tính CSS này:

page-break-after

page-break-before 

Ví dụ:

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

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

thông qua


Tôi không chắc chắn, bạn sẽ phải kiểm tra. Nếu không, hãy chia thành các mảng khác nhau và phân tách các mảng bằng một div trống
marcgg

Bạn sẽ phải áp dụng nó cho hàng của bảng hoặc thậm chí là ô, nhưng không phải cho bảng, tôi nghĩ vậy. Ngoài ra, nó nên hoạt động.
Pekka

2
không hoạt động trong chrome. Bị bỏ qua như thể
ladieu

5

Gần đây tôi đã giải quyết vấn đề này bằng một giải pháp tốt.

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

Hoạt động như một lá bùa!


2

Tôi đã kết thúc theo cách tiếp cận của @ Abbeyenteherrera, với một số điều chỉnh (có thể là bootstrap 3 cụ thể).

Về cơ bản; chúng tôi không thể phá vỡ trhoặc tdvì chúng không phải là các yếu tố cấp khối. Vì vậy, chúng tôi nhúng divs vào từng cái, và áp dụng các page-break-*quy tắc của chúng tôi chống lại div. Thứ hai; chúng tôi thêm một số phần đệm vào đầu của mỗi div này, để bù cho bất kỳ tạo tác tạo kiểu nào.

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

Các điều chỉnh lề và phần đệm là cần thiết để bù đắp một số loại jitter đã được giới thiệu (theo phỏng đoán của tôi - từ bootstrap). Tôi không chắc chắn rằng tôi đang trình bày bất kỳ giải pháp mới nào từ các câu trả lời khác cho câu hỏi này, nhưng tôi nghĩ có lẽ điều này sẽ giúp được ai đó.


1

Tôi đã đối mặt với cùng một vấn đề và cuối cùng tìm kiếm một giải pháp, cuối cùng, tôi tìm ra thứ gì đó phù hợp với tôi cho mọi trình duyệt.

html {
height: 0;
}

sử dụng css này hoặc Thay vì css bạn có thể có javascript này

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

Hy vọng điều này sẽ làm việc cho bạn là tốt.


0

Tôi đã kiểm tra nhiều giải pháp và bất cứ ai cũng không làm việc tốt.

Vì vậy, tôi đã thử một mẹo nhỏ và nó hoạt động:

t feet with style: position: fixed; bottom: 0px; được đặt ở cuối trang cuối cùng, nhưng nếu chân trang quá cao thì nó bị chồng chéo bởi nội dung của bảng.

chỉ với bàn chân: display: table-footer-group; không bị chồng chéo, nhưng không ở cuối trang cuối ...

Chúng ta hãy đặt hai bàn chân:

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>

Một vị trí dự trữ trên các trang không phải là cuối cùng, thứ hai đặt vào chân trang tình cờ của bạn.


-1

Tôi đã thử tất cả các đề xuất ở trên và thấy giải pháp trình duyệt chéo đơn giản và hiệu quả cho vấn đề này. Không có kiểu hoặc ngắt trang cần thiết cho giải pháp này. Đối với giải pháp, định dạng của bảng phải như sau:

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

Định dạng trên được thử nghiệm và làm việc trong các trình duyệt chéo


-2

Vâng, các bạn ... Hầu hết các Giải pháp ở đây không hoạt động. Vì vậy, đây là cách mọi thứ làm việc cho tôi ..

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>

Bộ đầu đầu tiên được sử dụng như một hình nộm để không bị thiếu đường viền trên cùng ở đầu thứ 2 (tức là đầu ban đầu) trong khi ngắt trang.


-3

Câu trả lời được chấp nhận không hoạt động với tôi trong tất cả các trình duyệt, nhưng sau css đã làm việc với tôi:

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

Cấu trúc html là:

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

Trong trường hợp của tôi, có một số vấn đề bổ sung với thead tr, nhưng điều này đã giải quyết vấn đề ban đầu là giữ cho các hàng của bảng không bị phá vỡ.

Vì các vấn đề tiêu đề, cuối cùng tôi đã kết thúc với:

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

Điều này đã không ngăn hàng bị phá vỡ; chỉ mỗi nội dung của mỗi tế bào.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.