html - 如何打破 CSS 中的报纸样式 3 列布局?

标签 html css flexbox css-grid css-multicolumn-layout

我有以下要求来设计打印布局以生成 pdf,并且我尝试了各种选项,包括 CSS flex 和 grid,但没有太大成功。
要求是:

  • 以 3 页的列布局显示内容 - 类似于报纸样式。
  • 如果一列包含太多信息,那么它将“流入”右侧的下一列。
  • 一旦我们达到 3 列的限制,那么第 4 列应该移动到下一行而不是列(如下一页)。此外,我们不知道总共有多少列或行。

  • 我能够达到第一个要求。但是,我找不到基于 div 宽度(或页面宽度)打破 CSS 中第三列的方法。
    我正在尝试以下代码:

    .newspaper {
      max-height: 500px;
       column-count: 3; 
      
    }
    .article {
      break-inside: avoid;
      page-break-after: always;        
    }
    .chart {
      background: #ccc;
      height: 200px;
    }
     <div class="newspaper">
          <div class="article">
            <h1>Article 1</h1>
            <div class="chart">Chart 1</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
              dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
              suscipit lobortis nisl ut aliquip ex ea commodo consequat.
            </p>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
              dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
              suscipit lobortis nisl ut aliquip ex ea commodo consequat.
            </p>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
              dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
              suscipit lobortis nisl ut aliquip ex ea commodo consequat.
            </p>
            <p>xxxxxxxxxx</p>
          </div>
          <div class="article">
            <h1>Article 2</h1>
            <div class="chart">Chart 2</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
              dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
              suscipit lobortis nisl ut aliquip ex ea commodo consequat.
            </p>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
              dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
              suscipit lobortis nisl ut aliquip ex ea commodo consequat.
            </p>
            <p>xxxxxxxxxx</p>
          </div>
          <div class="article">
            <h1>Article 3</h1>
            <div class="chart">Chart 3</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
              dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
              suscipit lobortis nisl ut aliquip ex ea commodo consequat.
            </p>
          </div>
    
          <div class="article">
            <h1>Article 4</h1>
            <div class="chart">Chart 4</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
              dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
              suscipit lobortis nisl ut aliquip ex ea commodo consequat.
            </p>
          </div>
          <div class="article">
            <h1>Article 5</h1>
            <div class="chart">Chart 5</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
              dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
              suscipit lobortis nisl ut aliquip ex ea commodo consequat.
            </p>
          </div>
          <div class="article">
            <h1>Article 6</h1>
            <div class="chart">Chart 6</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
              dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
              suscipit lobortis nisl ut aliquip ex ea commodo consequat.
            </p>
          </div>
          <div class="article">
            <h1>Article 7</h1>
            <div class="chart">Chart 7</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
              dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
              suscipit lobortis nisl ut aliquip ex ea commodo consequat.
            </p>
          </div>
        </div>

    预期输出:
    enter image description here
    只要它适用于 Chrome,我对任何 CSS 方法都很满意。
    谢谢。

    最佳答案

    当心:这是一种快速而肮脏的 hack,不建议在 Web 开发中使用,因为它会为它创建的每个页面制作整个文档的副本。然而,问题的范围似乎是一个从 HTML 创建 PDF 的私有(private)工具。对于那个用例,我认为这个技巧很合适。它符合您的所有标准,甚至跨页面并且响应迅速。
    何为诡计?
    正如其他人所提到的,CSS 目前没有提供一种自动方式来将列分成行并在它们之间流动文本。 display: grid做一些相关的事情,但保持盒子完好无损,这意味着元素不能在页面上以一个不间断的流形式流动。 flow-intoflow-from看起来很有希望,但尚未在您的首选环境(Chrome)中实现。
    诀窍
    此设置使用 columns 将您的整个内容分成列。属性,但使用带有 overflow: hidden 的容器仅显示其中三个.当页面加载一段 javascript 然后测量容器大小,将其与滚动溢出进行比较以确定隐藏了多少内容页面并相应地创建副本,每个副本都有一个偏移量,仅显示接下来的三个元素。因此,尽管每一页都包含整个文档,但结果是文章在页面上自由流动的错觉。
    尺寸可使用 .pages 中的变量进行配置。规则集。鉴于这种方法的骇人听闻的性质,进一步的风格定制可能需要一些修补。

    window.addEventListener("load", reflowPages);
    window.addEventListener("resize", reflowPages);
    
    function reflowPages() {
      const pages = document.querySelector(".pages");
      const template = document.querySelector(".page");
      if (pages == null || template == null) return;
    
      const viewportWidth = template.clientWidth;
      const totalWidth = template.scrollWidth;
      const pageCount = Math.ceil(totalWidth / viewportWidth);
    
      cleanPages();
      for (let n = 1; n < pageCount; n++) {
        const page = createPage(template, n);
        pages.appendChild(page);
      }
    }
    
    function cleanPages() {
      const [, ...rest] = document.querySelectorAll(".page");
      rest.forEach((v) => v.remove());
    }
    
    function createPage(template, n) {
      const element = template.cloneNode(true);
      element.style.setProperty("--page", n);
      return element;
    }
    .pages {
      --page-width: 100%;
      --page-height: 500px;
      --columns: 3;
    }
    
    .page {
      width: var(--page-width);
      height: var(--page-height);
      overflow: hidden;
      border-bottom: 1px solid black;
      padding: 1em 0;
    }
    
    .scroller {
      position: relative;
      max-height: 100%;
      column-count: var(--columns);
      column-gap: 0;
      left: calc(var(--page, 0) * -100%);
    }
    
    .article {
      padding: 0 0.5em;
      /* Instead of column-gap */
    }
    
    .chart {
      background: #ccc;
      height: 200px;
      break-inside: avoid;
    }
    <div class="pages">
      <div class="page">
        <div class="scroller">
          <div class="article">
            <h1>Article 1</h1>
            <div class="chart">Chart 1</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex
              ea commodo consequat.
            </p>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex
              ea commodo consequat.
            </p>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex
              ea commodo consequat.
            </p>
            <p>xxxxxxxxxx</p>
          </div>
          <div class="article">
            <h1>Article 2</h1>
            <div class="chart">Chart 2</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex
              ea commodo consequat.
            </p>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex
              ea commodo consequat.
            </p>
            <p>xxxxxxxxxx</p>
          </div>
          <div class="article">
            <h1>Article 3</h1>
            <div class="chart">Chart 3</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex
              ea commodo consequat.
            </p>
          </div>
    
          <div class="article">
            <h1>Article 4</h1>
            <div class="chart">Chart 4</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex
              ea commodo consequat.
            </p>
          </div>
          <div class="article">
            <h1>Article 5</h1>
            <div class="chart">Chart 5</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex
              ea commodo consequat.
            </p>
          </div>
          <div class="article">
            <h1>Article 6</h1>
            <div class="chart">Chart 6</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex
              ea commodo consequat.
            </p>
          </div>
          <div class="article">
            <h1>Article 7</h1>
            <div class="chart">Chart 7</div>
            <p>
              Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex
              ea commodo consequat.
            </p>
          </div>
        </div>
      </div>
    </div>

    缺点/限制
  • 根据文档的大小,这可能不是非常高效,但如前所述,这对于您的用例来说可能是可以接受的。
  • column-gap计算困惑,因此您应该使用 padding而是在子元素上(如示例中)
  • 给定多个页面,底部 .page将始终被不可见的溢出元素拉伸(stretch)到最大高度。
  • 关于html - 如何打破 CSS 中的报纸样式 3 列布局?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65625661/

    相关文章:

    javascript - 使用 JQuery 更改类中的 CSS 规则

    php需要textarea如何为每行设置一个硬限制

    html - 此时元素 img 不允许属性 img。错误

    php - 设置通过 phpmailer 发送的邮件的正文方向

    html - 如何将两个 div 垂直放置在顶部占据剩余高度的位置?

    html - 如何使用 flex-box 让页脚停留在页面底部

    html - Angular Flex 布局 : Responsive layout combining row and column

    python - 根据命名约定,使用 Python 在 Windows 中删除文件

    css - 如何垂直对齐div内的图像

    html - Flex 元素宽度不在 IE 中调整大小