使用 CSS 布局打印具有多列/行的 HTML 表格?

Posted

技术标签:

【中文标题】使用 CSS 布局打印具有多列/行的 HTML 表格?【英文标题】:Printing HTML table with many columns/rows using CSS layout? 【发布时间】:2015-01-02 19:58:45 【问题描述】:

我想从 html 打印一张大表格(大到它的行大约有 3 张纸宽)。如果可能,CSS 应该足以用于布局,并且解决方案应该适用于不同的浏览器。

我目前正在定义以下样式规则:

table  page-break-inside:auto; 
tr     page-break-inside:auto; 

当我检查 DOM 元素时,例如在 Firefox 33.0.2(在 OS X 上)我可以看到规则被识别,但是当我查看打印预览时( File | Print | PDF | 在预览中打开 PDF)所有不适合第一页的列都被切断,即我收到 1 页打印输出而不是 3 页。我也尝试过 Internet Explorer 11 和 10 效果相同。

那么我该如何布局大型 HTML 表格(最终无论是列还是行都很大)以便使用 CSS 打印出来?

额外问题:如果分页样式组件确实只适用于块级元素,如 this 上一个答案中所示,如果我从 divs 而不是 tds以打印输出为目标?

更新

这是我刚刚在 JSFiddle 上尝试过的相关示例。 (我在那里没有帐户,所以我无法提供直接链接。)

HTML:

<body>
<table>
<tr>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_0</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_1</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_2</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_3</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_4</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_5</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_6</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_7</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_8</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_9</td>
</tr>
</table>
</body>

CSS:

table  page-break-inside:auto; 
td     border:1px solid lightgray; 
tr     page-break-inside:auto; 

如果我尝试打印此表格(例如,通过应用 This Frame | Print Frame ... | PDF | Open PDF 预览 到 JSFiddle 的 Result 视图在 Firefox 33.1 for OS X 和纸张大小/方向 A4/Portrait)我得到一页输出。除第一列和第二列的一部分外,所有列都被截断。

【问题讨论】:

【参考方案1】:

如果您需要在页面上进行可读的垂直打印,您绝对需要远离桌子。表格非常适合在页面上显示当它是表格数据时,但不是一个可行的打印解决方案,因为它们不尊重流量。

有一些插件(如this one here, no affiliation – just a Google result)会自动为您执行此操作,但这里是示例。当您使用它时,请确保正确列出了@media print。要在本地测试,您可以将其更改为 @media screen

这不会显示列出的@page 规则,但可以通过打印预览看到这些规则。

希望这会有所帮助:

Fiddle for printing in portrait

HTML

<section class="table">
  <div class="row">
    <div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_0</div>
    <div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_1</div>
    <div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_2</div>
    <div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_3</div>
    <div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_4</div>
    <div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_5</div>
    <div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_6</div>
    <div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_7</div>
    <div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_8</div>
    <div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_9</div>
  </div>
</section>

CSS

@media print 
    @page 
      margin: 2.5cm;   
    
    div.row > div 
      display: inline-block;  
      border: solid 1px #ccc;
      margin: 0.2cm;
    
    div.row 
      display: block;
    



.table 
    display: table;
    border-spacing: 2px;

.row 
    display: table-row;

.row > div 
    display: table-cell;
    border: solid 1px #ccc;
    padding: 2px;

编辑 - 跨多个页面水平打印:

好的,所以这可能是一个不太常见的用例,我们必须用它做一些愚蠢的事情——这是公平的警告。我将尝试逐步解释这一点,因为它既神秘又令人讨厌。

Fiddle for printing in landscape here!

CSS

@media print 
    @page 
      margin: 0;
    
    body 
        height: 100%;
        width: 100%;
    
    div.row > div 
      display: inline-block;  
      border: solid 1px #ccc;
      margin: 0.1cm;
      font-size: 1rem;
    
    div.row 
      display: block;
      margin: solid 2px black;
      margin: 0.2cm 1cm;
      font-size: 0;
      white-space: nowrap;
    
    .table 
        transform: translate(8.5in, -100%) rotate(90deg);
        transform-origin: bottom left;
        display: block;
    

这是重要的部分,因为它正在设置您的打印指令。其中大部分是我们在原版中看到的(在我使用它时进行了一些调整)。

我们关心的部分在这里:

 .table 
     transform: translate(8.5in, -100%) rotate(90deg);
     transform-origin: bottom left;
     display: block;
 

我们正在做的是将整个事物翻转到一边,然后将其滑动到我们期望的位置。 translate(8.5in, -100%) 告诉浏览器 – 将此元素向右滑动 8.5 英寸(美国标准信纸的宽度),然后将其向上滑动 100% 的高度(负数表示向上而不是向下)。我们将它向右滑动 8.5 英寸,以便它在旋转时出现在页面顶部。我们将它向上滑动到计算出的高度,这样当旋转发生时,表格左侧也不会出现难看的间隙。

然后,我们指示它希望所有这些计算都相对于元素在文档流中的正常位置的bottom left 运行。通过设置left 属性,这可以防止这个疯狂的长表向右旋转。 bottom 属性很重要,因为我们将它顺时针旋转四分之一圈,如果我们从顶部进行旋转,它将离开页面左侧。 transform 声明的下一部分描述了该四分之一转:rotate(90deg);

瞧。东西打印在多个页面上。

在你问之前:不。没有办法防止在我知道的元素内分页。我知道它令人讨厌、丑陋和所有垃圾,但我们只能使用我们提供的工具。

更新 Firefox 确认工作:

【讨论】:

+1 请您修改一下,让它提供一个水平表格,其整个宽度打印在几页上。这是我原本打算的。 (这是迄今为止最有希望的答案。) @Drux - 更新了原版。很高兴我能帮上忙。 等等,为什么在@media print table, tbody, tr, th, td display: block; 可能的情况下对表格数据使用div 布局。顺便说一下 +1。 @SalmanA - 这也有效。我什至没有考虑到这一点。好点,+1。此处示例:fiddle.jshell.net/q5phvm68/12/show @SalmanA - 2 个小提琴和一个插件链接。我适当地标记了小提琴。【参考方案2】:

page-break-inside: auto; 是默认样式,因此除非您有不同的规则设置它们,否则这些规则将不起作用。

如果您的表格没有被分成多个页面,那么很可能是因为您添加了一些其他规则,这阻止了它 - 我猜是overflow: hidden

您首先应该做的是删除 所有 样式,并查看它是否会打印在多个页面上。如果是,请开始添加样式(逐条规则,或者如果需要,逐行添加)以查找问题。

【讨论】:

我刚刚尝试了您的建议(请参阅已编辑的问题),但仍然遇到同样的问题。您能否描述打印此表的可重现步骤? 这根本不能回答问题。 overflow: hidden 是我的问题。谢谢!【参考方案3】:

如果你想强制分页,你应该使用 page-break-beforepage-break-after。您需要知道样式元素应该包含一个非空的块级元素并且它不能绝对定位。但是,它在表格元素上非常不一致。这就引出了您的最后一个问题:是的,使用divs 构建您的表会更加一致。

但是,考虑到您想要实现的目标(打印大型水平表格),您应该知道尝试将 3 页放入 1 页是行不通的,因为您的内容不可读。 事实上,唯一的最佳做法是改用垂直布局(仅用于打印或同时用于网络和打印)。

【讨论】:

+1 您是否有一篇文章的参考,该文章为在这种情况下替代使用垂直布局提供了令人信服的论据。这可能会说服客户改变当前的要求。 @Drux 当然。您能否为表格提供更多背景信息,以便我给您提供相关示例?比如表的目的是什么? 列对应一个时间段。这些行对应于具有相关事件的对象,这些事件是在该期间的特定日期安排的。单元格包含事件 ID。事件 ID 足够长,以至于在很长一段时间内(例如 2 个月),表格可能比单个打印页面宽。不管怎样,打印它会很好(可能在每个水平打印页面上重复对象 ID 的标题列)。

以上是关于使用 CSS 布局打印具有多列/行的 HTML 表格?的主要内容,如果未能解决你的问题,请参考以下文章

css3多列布局

十天精通CSS3(10)

表格中特定行的边框?

css多列布局

CSS多列布局Multi-column伸缩布局Flexbox网格布局Grid详解

CSS 垂直居中多列布局