How to prevent column break within an element?

227.9k Views Asked by At

Consider the following HTML:

<div class='x'>
    <ul>
        <li>Number one</li>
        <li>Number two</li>
        <li>Number three</li>
        <li>Number four is a bit longer</li>
        <li>Number five</li>
    </ul>
</div>

and the following CSS:

.x {
    -moz-column-count: 3;
    column-count: 3;
    width: 30em;
}

As it stands, Firefox currently renders this similarly to the following:

• Number one    • Number three          bit longer
• Number two    • Number four is a    • Number five

Notice that the fourth item was split between the second and third column. How do I prevent that?

The desired rendering might look something more like:

• Number one    • Number four is a
• Number two      bit longer
• Number three  • Number five

or

• Number one    • Number three        • Number five
• Number two    • Number four is a
                  bit longer

Edit: The width is only specified to demonstrate the unwanted rendering. In the real case, of course there is no fixed width.

19

There are 19 best solutions below

14
On BEST ANSWER

The correct way to do this is with the break-inside CSS property:

.x li {
    break-inside: avoid-column;
}

Unfortunately, as of October 2021, this is still not supported in Firefox but it is supported by every other major browser. With Chrome, I was able to use the above code, but I couldn't make anything work for Firefox (See Bug 549114).

The workaround you can do for Firefox if necessary is to wrap your non-breaking content in a table but that is a really, really terrible solution if you can avoid it.

UPDATE

According to the bug report mentioned above, Firefox 20+ supports page-break-inside: avoid as a mechanism for avoiding column breaks inside an element but the below code snippet demonstrates it still not working with lists:

.x {
    column-count: 3;
    width: 30em;
}

.x ul {
    margin: 0;
}

.x li {
    -webkit-column-break-inside: avoid;
    -moz-column-break-inside:avoid;
    -moz-page-break-inside:avoid;
    page-break-inside: avoid;
    break-inside: avoid-column;
}
<div class='x'>
    <ul>
        <li>Number one, one, one, one, one</li>
        <li>Number two, two, two, two, two, two, two, two, two, two, two, two</li>
        <li>Number three</li>
    </ul>
</div>

As others mention, you can do overflow: hidden or display: inline-block but this removes the bullets shown in the original question. Your solution will vary based on what your goals are.

UPDATE 2 Since Firefox does prevent breaking on display:table and display:inline-block a reliable but non-semantic solution would be to wrap each list item in its own list and apply the style rule there:

.x {
    -moz-column-count: 3;
    -webkit-column-count: 3;
    column-count: 3;
    width: 30em;
}

.x ul {
    margin: 0;
    page-break-inside: avoid;           /* Theoretically FF 20+ */
    break-inside: avoid-column;         /* Chrome, Safari, IE 11 */
    display:table;                      /* Actually FF 20+ */
}
<div class='x'>
    <ul>
        <li>Number one, one, one, one, one</li>
    </ul>
    <ul>
        <li>Number two, two, two, two, two, two, two, two, two, two, two, two</li>
    </ul>
    <ul>
        <li>Number three</li>
    </ul>
</div>

0
On

This answer might only apply to certain circumstances; If you set a height to your elements, this will be obeyed by the column styling. There-by keeping anything that is contained within that height to a row.

I had a list, like the op, but it contained two elements, items and buttons to act upon those items. I treated it like a table <ul> - table, <li> - table-row, <div> - table-cell put the UL in a 4 column layout. The columns were sometimes being split between the item and it's buttons. The trick I used was to give the Div elements a line height to cover the buttons.

0
On

Firefox 26 seems to require

page-break-inside: avoid;

And Chrome 32 needs

-webkit-column-break-inside:avoid;
   -moz-column-break-inside:avoid;
        column-break-inside:avoid;
0
On

Most of the propertis is showing invalid when I am going to apply such as

  page-break-inside: avoid-column;
  break-inside: avoid-column;
  -webkit-column-break-inside: avoid-column; 

and when I am checking is responsiveness it not working fine for me...

Anyone can provide me a solution for the same...

1
On

I faced same issue while using card-columns

i fixed it using

 display: inline-flex ;
 column-break-inside: avoid;
 width:100%;
4
On

The accepted answer is now two years old and things appear to have changed.

This article explains the use of the column-break-inside property. I can't say how or why this differs from break-inside, because only the latter appears to be documented in the W3 spec. However, the Chrome and Firefox support the following:

li {
    -webkit-column-break-inside:avoid;
       -moz-column-break-inside:avoid;
            column-break-inside:avoid;
}
9
On

Adding;

display: inline-block;

to the child elements will prevent them being split between columns.

1
On
<style>
ul li{display: table;}  
</style>

works perfectly

0
On

In 2019, having this works for me on Chrome, Firefox and Opera (after many other unsuccessful attempts):

.content {
    margin: 0;
    -webkit-column-break-inside: avoid;
    break-inside: avoid;
    break-inside: avoid-column;
}

li {
    -webkit-column-break-inside:avoid;
       -moz-column-break-inside:avoid;
            column-break-inside:avoid;
           break-inside: avoid-column;
             page-break-inside: avoid;
}
0
On

I just fixed some divs that were splitting onto the next column by adding

overflow: auto

to the child divs.

*Realized it only fixes it in Firefox!

1
On

This works for me in 2015 :

li {
  -webkit-column-break-inside: avoid;
  /* Chrome, Safari, Opera */
  page-break-inside: avoid;
  /* Firefox */
  break-inside: avoid;
  /* IE 10+ */
}
.x {
  -moz-column-count: 3;
  column-count: 3;
  width: 30em;
}
<div class='x'>
  <ul>
    <li>Number one</li>
    <li>Number two</li>
    <li>Number three</li>
    <li>Number four is a bit longer</li>
    <li>Number five</li>
  </ul>
</div>

3
On

Firefox now supports this:

page-break-inside: avoid;

This solves the problem of elements breaking across columns.

2
On

set following to the style of the element that you don't want to break:

overflow: hidden; /* fix for Firefox */
break-inside: avoid-column;
-webkit-column-break-inside: avoid;
1
On

As of October 2014, break-inside still seems to be buggy in Firefox and IE 10-11. However, adding overflow: hidden to the element, along with the break-inside: avoid, seems to make it work in Firefox and IE 10-11. I am currently using:

overflow: hidden; /* Fix for firefox and IE 10-11  */
-webkit-column-break-inside: avoid; /* Chrome, Safari, Opera */
page-break-inside: avoid; /* Firefox */
break-inside: avoid; /* IE 10+ */
break-inside: avoid-column;
0
On

I had the same problem i think and found a solution in this:

-webkit-column-fill: auto; /* Chrome, Safari, Opera */
-moz-column-fill: auto; /* Firefox */
column-fill: auto;  

Working also in FF 38.0.5: http://jsfiddle.net/rkzj8qnv/

0
On

I made an update of the actual answer.

This seems to be working on firefox and chrome: http://jsfiddle.net/gatsbimantico/QJeB7/1/embedded/result/

.x{
columns: 5em;
-webkit-columns: 5em; /* Safari and Chrome */
-moz-columns: 5em; /* Firefox */
}
.x li{
    float:left;
    break-inside: avoid-column;
    -webkit-column-break-inside: avoid;  /* Safari and Chrome */
}

Note: The float property seems to be the one making the block behaviour.

0
On

The following code works to prevent column breaks inside elements:

-webkit-column-break-inside: avoid;
-moz-column-break-inside: avoid;
-o-column-break-inside: avoid;
-ms-column-break-inside: avoid;
column-break-inside: avoid;
1
On

Try this:

-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid;
-webkit-column-break-inside: avoid-column;
page-break-inside: avoid-column;
break-inside: avoid-column;

...worked for me, might work for you.

1
On

A possible workaround for Firefox is to set the CSS property "display" of the element you don't want to have a break inside to "table". I don't know if it works for the LI tag (you'll probably lose the list -item-style), but it works for the P tag.