3

I have a layout with column-width: 20em; that contains a definition list. Sometimes a dt will get stranded at the bottom of a column and it's dd is at the top of the next column.

There's a live example here. (Although not totally cleanly cut down to a minimal example.)

enter image description here

See the bottom of the first and third columns.

I know I can control the breaks inside an element with widows, orphans and column-break-inside, but is there a way to make the two elements behave as one?

This question is about a similar problem, but it doesn't feel like each dt dd pair is semantically a section.

Community
  • 1
  • 1
Ben
  • 12,614
  • 4
  • 37
  • 69

2 Answers2

4

Although multi-column layout as such is relatively widely supported in modern browsers, the control of column breaks is poorly implemented. Implementations mostly support just prevention of column breaks inside an element, not after or before an element. Thus, although you could in theory use break-before or break-after property, you need to use break-inside in practice. (According to MDN, IE 10+ supports break-after: avoid-column, but setting it on dt did not seem to have any effect on IE 11.)

You cannot use anything except dt and dd inside a dl. This is not just a formal rule; browsers actually enforce it, ignoring any attempts at using a wrapper around a dt and a dd. This is really a design flaw in the very dl element.

Thus, what you can do is to use other markup instead of dl, e.g.

<div class=dl>
  <div class=pair>
    <div class=dt>...</div>
    <div class=dt>...</div>
  </div>
  <div class=pair>
    <div class=dt>...</div>
    <div class=dt>...</div>
  </div>
  ...
</div>

You can then style it this way:

.dl {
  -webkit-column-width: 20em;
  -moz-column-width: 20em;
  column-width: 20em;
}
.dd { 
  margin-left: 1em;
}
.pair {
  break-inside: avoid-column;
  -webkit-column-break-inside: avoid;
}

This prevents the undesired column breaks in modern versions of IE and in Chrome. I’m afraid there’s no way to make it work on Firefox.

Update: It seems that if you wrap the <div class=pair> element inside a single-cell table, <table><tr><td><div class=pair>...</div></table>, then Firefox does not break that element in column formatting. Perhaps the reason is that it generally tries to avoid column breaks inside a table cell, which is rather sensible.

Jukka K. Korpela
  • 195,524
  • 37
  • 270
  • 390
  • 1
    One day soon... It isn't super important at the moment, so I'll just throw the css that's supposed to work in and then one day it'll just magically look better. – Ben Jul 30 '14 at 07:50
  • You saved my day. To fix firefox problem, you can just add `overflow: hidden` inside `pair` class – Florian Nov 06 '18 at 10:17
  • 1
    9 years later, but Edge at least seems to obey {break-after:avoid-column;} just fine. So @Ben's idea to put in the correct CSS and hope was the right thing to do. – Martha Aug 01 '23 at 18:49
0

This took a while! @Martha pointed out that this now works in Edge, and I just checked and it works in chrome.

If you set the dt to have:

dt {  break-after:avoid-column; }

Then it'll stay with whatever is behind it. You can try adding it to the demo in the question and it magically works.

Ben
  • 12,614
  • 4
  • 37
  • 69