页边距和背景图片

时间:2017-09-09 12:23:23

标签: html css printing sass

我正在尝试创建一个HTML文档,以便使用CSS自动设置它并轻松地从中生成PDF文件(到现在为止,我一直在使用Chrome,但我正在思考一个基于WKHTML2PDF的解决方案)。这是我到目前为止创建的结构:

<body class="preview">
   <main class="document">
      <div class="page">
         <div class="text-flow-page-content"><!-- <p>Page content... --></div>
      </div>
      <div class="page with-column-separator">
         <div class="simple-page-column"><!-- <p>Page content... --></div>
         <div class="simple-page-column"><!-- <p>Page content... --></div>
      </div>
      <div class="page with-ribbon">
         <div class="text-flow-page-content"><!-- <p>Page content... --></div>
      </div>
   </main>
</body>

形成SCSS观点:

  • .preview是顶级容器;它包含页面以及JS快速主题切换器。
  • .document是所有页面的容器; @media print { .preview > *:not(.document) { display: none; } }使其成为最终印刷的唯一元素。
  • .page代表一个页面;每个页面都可以通过添加装饰类来单独定制(例如:.with-ribbon.with-column-separator)。
  • %page-content以及扩展它的所有内容(例如text-flow-page-contentsimple-page-column)代表页面的内容。

其中包含以下内容:

+------------------------+
|           PP           |
|    +--------------+    |
|    |    +----+    |    |
|    |    | CT |    |    |
|    |    | CT |    |    |
| PP | CM | CT | CM | PP |
|    |    | CT |    |    |
|    |    | .. |    |    |
|    |    +----+    |    |
|    +--------------+    |
|           PP           |
+------------------------+

其中:

  • PP代表&#34; Page Padding&#34;,即.page { padding: ...
  • CM代表&#34;内容保证金&#34;,适用时为.simple-page-column { margin: ...
  • CT代表&#34;内容文字&#34;,即<div class="simple-page-column"><p>Content Text...

你可能已经受够了我的生命。当页面溢出时,我遇到了一点陷阱:页面填充不适用:

enter image description here

当然,我可以使用页面边距设置@page { margin: ...,但它会裁剪由background-image装饰类初始化的页面.page.with-ribbon

enter image description here

因此我的问题是:如何在不将背景的一部分变成肮脏的白色笔划的情况下应用我的页面填充?

编辑:这是一个演示(可运行的演示似乎&#34;打印&#34;非常好,所以我认为最好给出一个代码完整档案):

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8" />
      <title>Print me</title>
      <style>
         @media screen {
            .preview { background: #DDD; }

            .preview .page {
               margin: 20pt auto;
               width: 21cm;
               min-height: 29.7cm;

               background-color: #FFF;
            }
         }

         @media print { .preview > *:not(.document) { display: none; } }

         @page { margin: 0; }

         .page {
            display: flex;

            padding: 0.78in;

            background-image: url("https://i.stack.imgur.com/2q5wa.png");
            background-repeat: no-repeat;
            background-position: -10pt 10pt;
            background-size: 6cm;

            page-break-before: always;
            page-break-inside: avoid;
            page-break-after: always;
         }

         .text-flow-page-content { flex: 1; }
      </style>
   </head>
   <body class="preview">
       <main class="document">
            <div class="page">
                <div class="text-flow-page-content">
                     <h1>Simple Page</h1>
                     <h4>Pages? Gotta print them all!</h4>
                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut ac quam dictum, mollis dui et, blandit est. Proin et consectetur quam.</p>
                </div>
            </div>
            <div class="page">
                <div class="text-flow-page-content">
                     <h1>Page with Overflow</h1>
                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut ac quam dictum, mollis dui et, blandit est. Proin et consectetur quam. Vivamus non vulputate mi, et scelerisque mi. Curabitur orci mi, dignissim eget faucibus pulvinar, tristique nec lacus. Suspendisse lobortis nec odio sit amet volutpat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum tempor nisi nisl, ut porttitor risus blandit non. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec est ligula, aliquam sit amet pretium vehicula, ultrices non nulla. Vivamus tristique hendrerit tincidunt. Nunc eu lorem accumsan, accumsan risus quis, aliquam erat. Praesent ut maximus tortor, vitae scelerisque nisl. Vivamus tellus nibh, rutrum at magna eu, gravida pulvinar felis.</p>
                     <p>Vivamus sodales vel sem sit amet feugiat. Maecenas consectetur auctor bibendum. Nunc ac vestibulum augue. Aliquam eget sollicitudin dui, mattis auctor augue. Ut ultricies sit amet augue et sagittis. Nunc dignissim lectus id ligula facilisis tincidunt. Pellentesque ullamcorper malesuada lectus. Vestibulum lacinia, ipsum ultrices mattis porttitor, justo urna dictum quam, in suscipit lectus velit vel eros. Vivamus vehicula, lorem eu tincidunt malesuada, lectus mauris ornare lectus, nec viverra nisl ligula nec metus. Etiam malesuada ultrices feugiat. Vestibulum sollicitudin pulvinar orci eu imperdiet. Ut quis lectus vel ante congue eleifend. Nunc ac odio risus. Quisque at suscipit lectus, aliquam cursus lectus. Pellentesque condimentum tellus vitae purus elementum posuere. Aliquam laoreet arcu lectus, vel vehicula arcu lobortis ac.</p>
                     <p>Fusce sit amet ex sit amet enim dictum ornare. Praesent urna libero, vulputate quis facilisis id, pharetra non augue. Praesent porta ligula vel fermentum elementum. In volutpat libero massa, sed ornare lectus porttitor id. Fusce malesuada venenatis turpis, sed posuere risus sodales quis. Aliquam pretium sollicitudin massa, a sollicitudin mi volutpat at. Integer accumsan, sapien quis congue luctus, elit magna semper quam, et vulputate lorem tellus nec urna. Cras condimentum efficitur massa id dignissim. Nulla et auctor libero, id pretium sem. Donec ante nibh, iaculis id egestas vitae, fringilla id neque. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam maximus tempor pellentesque. Donec accumsan finibus malesuada. Aenean vitae lorem interdum, scelerisque turpis nec, semper sapien.</p>
                     <p>Nunc non fringilla sapien, quis tincidunt turpis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nulla facilisi. Nullam ultrices ullamcorper tempus. Proin a commodo sapien. Phasellus auctor tortor a neque elementum luctus. Quisque venenatis turpis nisl, vel lacinia metus faucibus a. Donec diam arcu, vestibulum auctor dui tincidunt, euismod luctus massa. Nullam sed rutrum mauris, porta interdum velit. Maecenas sodales vel nunc vel sodales. Integer ultricies elit vel iaculis mollis. Ut lectus est, lobortis ut turpis a, cursus pulvinar dui. Fusce blandit augue tempus viverra tempor.</p>
                     <p>Maecenas in scelerisque tortor, ut suscipit lectus. Pellentesque et tortor consequat, faucibus dolor vitae, iaculis lectus. Donec tempus, urna in tincidunt pellentesque, lectus dolor semper velit, eget aliquet nisi arcu in velit. Nulla dignissim eget nunc ut faucibus. Nunc pulvinar justo eget mauris semper commodo. Maecenas eu dapibus elit. Duis sodales at eros sit amet scelerisque. Fusce nisl lacus, scelerisque vestibulum enim et, placerat finibus augue. Nunc lacinia dui eu elit consequat, eget consequat risus volutpat. Nulla vestibulum lobortis est vitae pharetra.</p>
                     <p>Mauris cursus, lacus sed consequat tempus, erat tortor auctor justo, ut venenatis metus erat vitae nunc. Pellentesque porta ex eget mattis eleifend. Mauris accumsan tortor turpis, maximus volutpat quam cursus vel. Nullam rutrum sed ipsum vitae dictum. Sed dapibus quis urna quis vulputate. Vivamus at augue ut mauris vehicula finibus. Nulla nec mattis massa.</p>
                     <p>Sed commodo nec diam nec hendrerit. Sed ultricies justo ante, vel ornare dolor tempus vitae. In hac habitasse platea dictumst. Suspendisse a sodales magna, et consectetur nisi. Vivamus tincidunt, orci eget porttitor viverra, augue libero cursus metus, sit amet molestie metus nibh ullamcorper ex. Donec quis risus et lectus auctor rhoncus eu id quam. Donec mollis arcu est. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam ante nisi, suscipit non nisl ut, facilisis pretium eros. Curabitur non justo non magna rutrum vulputate et in ligula.</p>
                     <p>Vestibulum viverra, quam eget dapibus porttitor, dui massa auctor velit, vitae finibus nisi mauris a urna. Nulla iaculis purus sit amet dapibus pharetra. Fusce sollicitudin luctus odio placerat congue. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis pellentesque, velit sed eleifend ullamcorper, velit orci posuere enim, a commodo massa ex a leo. Nullam rutrum nulla in dolor scelerisque, non lobortis nulla lobortis. Etiam hendrerit purus vitae leo imperdiet vehicula. Nulla ac nisl at magna placerat dapibus. Proin ex est, suscipit ac ex in, commodo convallis nisl. Cras sed leo eu erat suscipit dapibus. Quisque sed justo sed mi tempus mattis.</p>
                     <p>Nullam accumsan eros neque, vel ornare odio convallis accumsan. Fusce mollis pretium luctus. Nulla ut diam eu sem blandit scelerisque. Integer ac tempor quam. Praesent euismod orci mi, vitae volutpat libero iaculis eu. Nunc fringilla vulputate laoreet. Vestibulum condimentum ut ante eu aliquam. Cras feugiat, diam a fringilla posuere, ligula arcu consequat lacus, a vestibulum lectus lectus a neque. Suspendisse efficitur semper placerat. Curabitur non sollicitudin ante. Nullam convallis neque egestas auctor vehicula. Sed nec laoreet enim, a volutpat sem.</p>
                     <p>Mauris pellentesque fermentum nibh, a pretium turpis dictum in. Pellentesque sed sapien pharetra, lobortis ex at, auctor quam. Phasellus tristique, ex vel eleifend sagittis, nisi nunc malesuada leo, at blandit neque nisl in justo. Phasellus tincidunt odio ut libero blandit, sit amet feugiat leo egestas. Praesent porttitor, augue non sagittis elementum, odio turpis luctus nisi, at elementum odio nulla molestie elit. Nunc eget arcu bibendum, gravida eros ac, condimentum lorem. Aliquam scelerisque mi quis urna venenatis, fermentum mollis lacus efficitur. Aliquam aliquet quis dolor pulvinar ullamcorper. Ut non ornare felis, eget condimentum orci. Etiam egestas cursus sem, et sodales felis pellentesque sodales. Morbi dapibus accumsan erat, ut luctus sapien consequat feugiat. Nulla eu euismod ex, nec commodo est. Etiam ultrices tincidunt nulla vel sodales.</p>
                     <p>Vivamus egestas, metus et vehicula facilisis, nisi diam dictum nisi, eget suscipit tortor ligula at mauris. Nunc malesuada nisi quis ligula volutpat egestas. Aliquam blandit ut velit a molestie. Sed eu dictum orci. Etiam congue purus sit amet luctus tempus. Nullam augue mauris, posuere ut aliquet pulvinar, posuere et augue. Morbi urna est, cursus ut erat at, tristique ultricies velit.</p>
                     <p>Nulla facilisis vehicula eros, vitae venenatis eros consequat id. Nam dapibus lacus tellus, quis porttitor justo feugiat semper. Maecenas vel tellus enim. Duis sed elit dui. Nulla commodo erat blandit orci tempor, non sagittis tellus imperdiet. Aliquam consectetur, sem ac aliquam molestie, lectus nulla porta urna, suscipit maximus nunc eros id dui. Donec eu nulla eu ipsum placerat tristique eget in massa. Sed fringilla quam vel nisi interdum luctus in vel magna. Vivamus dictum, nulla nec ullamcorper euismod, mauris mi bibendum mi, nec ultrices leo turpis sed tortor.</p>
                </div>
            </div>
       </main>
   </body>
</html>

尝试打印它。问题出现在第2页和第3页之间:打印时,当内容溢出并触发分页时,页面垂直(顶部和底部)边距不适用。

1 个答案:

答案 0 :(得分:0)

我终于选择了基于JS的解决方案;请评价我的代码,它使用我问题的第一个代码块中提供的HTML结构:

const MAX_PAGE_CONTENT_HEIGHT = 972.34
const MAX_PAGE_CONTENT_HEIGHT_WITH_RIBBON = 934.80

const PAGE_BREAK_CLASS = "computed-page-break"
const RIBBON_DECORATION_CLASS = "with-ribbon"

for (const pageContent of document.getElementsByClassName('text-flow-page-content')) {
   let firstPage = true
   let currentPageContentHeight = 0

   let previousElementMarginBottom = 0

   for (const element of pageContent.children) {
      // Compute element height.
      const elementStyle = getComputedStyle(element)

      // Hack: 'cuz of margin merging, the biggest margin has to be chosen
      // between this element's top margin and the previous one's bottom margin.
      const elementFullHeight = parseFloat(elementStyle.height) + Math.max(
         parseFloat(elementStyle.marginTop),
         parseFloat(previousElementMarginBottom)
      )

      previousElementMarginBottom = parseFloat(elementStyle.marginBottom)

      // Simulate the insertion of the element to the virtual page,
      // and see if it make the content height exceed the maximum.
      if ((
         // Special treatment: extra margin on the first page due to decoration.
         firstPage &&
         pageContent.parentElement.classList.contains(RIBBON_DECORATION_CLASS) &&
         currentPageContentHeight + elementFullHeight > MAX_PAGE_CONTENT_HEIGHT_WITH_RIBBON
      ) || (
         currentPageContentHeight + elementFullHeight > MAX_PAGE_CONTENT_HEIGHT
      )) {
         // In that case:
         //    - Reset the virtual page;
         //    - Put a page break mark;
         //    - Add the element to the new virtual page.
         firstPage = false
         element.classList.add(PAGE_BREAK_CLASS)
         currentPageContentHeight = elementFullHeight
      } else {
         // Otherwise, just add the element to the virtual page.
         currentPageContentHeight += elementFullHeight
      }
   }
}

注意:只是说.page.with-ribbon装饰类会为页面添加背景图片和额外的页边距...我发布的代码将此考虑在内,其他任何人都觉得它没用。