I have a multi-column div (2-4 columns depending on a setting in my app) generated live by user-provided markdown in a text editor. In some cases, they want to manually insert column breaks. To achieve this, I provide a Markdown snippet that generates a div with the CSS property break-after: column
to manually trigger column breaks. It works fine if it is set to display: block
. However, if the user then inserts a div that spans both columns (with CSS column-span: all
), that column-spanning element gets shunted to below its containing element, and any further text disappears entirely, as follows (in the latest version of Chrome, specifically):
.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>
This is what it looks like (note the "more columns after" paragraphs are missing):
Changing the colbreak
to have display: inline-block
or otherwise just seems to ignore the break-after: column
altogether (perhaps this is the real question: Why is break-after
ignored for my inline-block element?:
As shown below, I get the same behavior by simply not including the colbreak
div at all:
Can anyone explain how to achieve the desired behavior? Since this is being rendered live as the user types it in, I would like to maintain the automatic balancing of columns by not requiring a separate div
for each column. Calculating text length and height and moving them between columns on the fly as it is typed seems more trouble than it's worth. This also stops working if the user changes to a setting with
How to achieve close to desired result:
I think css-multicol will be good read if you want to understand bit more about multi-column css support.
Main issue with your current css is height
in container
. To fix that, you can put container inside another div
and style it with your desired style, that will give you as much as you can get close to your desired result.
.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>
Why height on container is not working as expected?
I believe that is by design, at least from my understanding based on reading the spec, which says:
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.
Update:
Why is break-after ignored for my inline-block element?:
That is because break-word
is supposed to be working only for block-level elements as per W3C guidelines.
Original answer:
You need to wrap your column content into separate div and apply column-count
style to that div and it will work.
.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>
or you can use CSS grid:
.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>