防止 CSS `column-span: all` 分流到页面底部

Prevent CSS `column-span: all` shunting to bottom of page

我有一个多列 div(2-4 列,具体取决于我的应用程序中的设置)由用户在文本编辑器中提供的 markdown 实时生成。在某些情况下,他们希望手动插入分栏符。为实现这一点,我提供了一个 Markdown 片段,它生成一个 div 和 CSS 属性 break-after: column 来手动触发分栏符。如果设置为 display: block,它工作正常。但是,如果用户随后插入跨越两列的 div(使用 CSS column-span: all),则该跨越列的元素将被分流到 下面的 它的包含元素,以及任何进一步的文本完全消失,如下所示(在最新版本的 Chrome 中):

.container {
  column-count: 2;
  height: 60mm;
  border: solid black 1px;
}

.container .colbreak {
 color: red;
 break-after: column;
}

.container .wide {
  color: blue;
  column-span: all;
}
<div class="container">

  <p>left left left</p>
  <p>left left left</p>
   
  <div class="colbreak">Column Break</div>
  
  <p>right right right</p>
  <p>right right right</p>
  <p>right right right</p>
  <p>right right right</p>
  <p>right right right</p>

  <div class="wide">
    span all span all span all
    span all span all span all
    span all span
  </div>
  
  <p>more columns after</p>
  <p>more columns after</p>
  <p>more columns after</p>
  <p>more columns after</p>

</div>

这是它的样子(注意“后面的更多列”段落丢失):

colbreak 更改为 display: inline-block 或以其他方式似乎完全忽略了 break-after: column(也许这是 真正的 问题: 为什么我的内联块元素 break-after 被忽略了?:

如下所示,我通过根本不包括 colbreak div 得到了相同的行为:

任何人都可以解释如何实现所需的行为吗?由于这是在用户输入时实时呈现的,因此我想通过不需要为每一列单独设置 div 来保持列的自动平衡。计算文本长度和高度并在键入时在列之间动态移动它们似乎比它的价值更麻烦。如果用户更改为

的设置,这也会停止工作

如何达到接近预期的结果:

如果您想更多地了解 multi-column css 支持,我认为 css-multicol 会很好。

您当前 css 的主要问题是 container 中的 height。要解决此问题,您可以将容器放入另一个 div 中并根据您想要的样式设置样式,这将尽可能接近您想要的结果。

.main-container {
  height: minmax(min-content, 100mm);
  overflow: auto;
  border: solid black 1px;
}

.container {
  column-count: 2;
}

.container .colbreak {
  color: red;
  break-after: column;
}

.container .wide {
  color: blue;
  column-span: all;
}
<div class="main-container">
  <div class="container">
    <p>left left left</p>
    <p>left left left</p>

    <div class="colbreak">Column Break</div>

    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>

    <div class="wide">
      span all span all span all span all span all span all span all span
    </div>

    <p>more columns after</p>
    <p>more columns after</p>
    <p>more columns after</p>
    <p>more columns after</p>
  </div>
</div>

为什么容器上的高度没有按预期工作?

我相信这是设计使然,至少根据我阅读规范的理解,它说:

An element that spans more than one column is called a spanning element and the box it creates is called a spanner.

A spanning element is taken out-of-flow, leaving a forced break. This does not affect the painting order [CSS21] of the spanning element.

更新:

Why is break-after ignored for my inline-block element?:

那是因为 break-word 应该只适用于 block-level elements as per W3C guidelines

原回答: 您需要将您的专栏内容包装到单独的 div 中并将 column-count 样式应用到 div 并且它会起作用。

.container {
  height: 100mm;
  border: solid black 1px;
}

.col2 {
  column-count: 2;
}

.container .colbreak {
  break-after: column;
}

.container .wide {
  color: blue;
  column-span: all;
}
<div class="container">
  <div class="col2">
    <p>left left left</p>
    <p>left left left</p>
    <p>left left left</p>

    <div class="colbreak">Column Break</div>

    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
  </div>
  <div class="wide">
    span all span all span all span all span all span all span all span all span all span all span all span all span all span all span all
  </div>

</div>

或者你可以使用CSS网格:

.container {
  height: 100mm;
  border: solid black 1px;
  display: grid;
  grid-template-columns: 50% 50%;
}

.container .wide {
  color: blue;
  grid-column-start: 1;
  grid-column-end: -1;
}
<div class="container">
  <div>
    <p>left left left</p>
    <p>left left left</p>
    <p>left left left</p>
  </div>
  <div>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
  </div>
  <div class="wide">
    span all span all span all span all span all span all span all span all span all span all span all span all span all span all span all
  </div>
</div>

您可以尝试将列分成 2 个 div。它会将它们分开,允许将它们设置为单独的列,而不必插入分隔符。

.column {
  float: left;
  width: 50%;
}
<div class="container">
  <div class="column">
    <p>left left left</p>
    <p>left left left</p>
    <p>left left left</p>
  </div>

  <div class="column">
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
    <p>right right right</p>
  </div>

  <div class="wide">
    span all span all span all span all span all span all span all span all span all span all span all span all span all span all span all
  </div>
</div>

建议您重构 HTML 代码并使用 flexbox。它会让您更好地控制 div 的位置以及您想要使用它的内容的方式。此外,使用 flexbox 很容易做出响应。

.container{
  width: 50%;
  border: 1px solid black;
}

.container .flex {
  display:flex;
  flex-direction: row;
  justify-content: space-around;
}

.container .wide {
  color: blue;
  column-span: all;
}
<div class="container">
  <div class="flex">
    <div>
  <p>left left left</p>
  <p>left left left</p>
  <p>left left left</p>
   <p>left left left</p>
 
   <p>left left left</p>
  <p>left left left</p>
  <p>left left left</p>
   <p>left left left</p>
  <p>left left left</p>
  <p>left left left</p>
   
  <div class="colbreak">Column Break</div>
  </div>
  <div class="flex-2">
  <p>right right right</p>
  <p>right right right</p>
  <p>right right right</p>
  <p>right right right</p>
  <p>right right right</p>
  <p>right right right</p>
  <p>right right right</p>
  </div>
</div>

<div class="wide">
  
  span all span all span all
  span all span all span all
  span all span all span all
  span all span all span all
  span all span all span all
</div>
</div>