Search code examples
htmlcsshtml-lists

How can I lay out a definition list with <dt>s and <dd>s side-by-side but the <dd>s move down if the <dt>s get longer?


I'd like to lay out a definition list <dl> with the <dt> elements in one column and their corresponding <dd> elements in another.

The tricky part is that I want my <dt>s never to wrap, and if they are too wide for the first column, I want the <dd> elements to move down to make room:

Here's a screenshot of what I'm aiming for:

the desired result, as described above

And here's an ASCII art version:

first dt     first dd goes here and can be any length

second dt    second dd is here and also any length

a much longer dt that overlaps
             third dd moves down to make room

last dt      last dd

The closest I've gotten is to use flexbox to place the elements side by side and then manually adjust the positioning of <dd> elements attached to long <dt> elements:

dl {
  display: flex;
  flex-flow: row wrap;
}
dt {
  flex-basis: 10em;
  white-space: nowrap;
}
dd {
  flex-basis: calc(100% - 10em);
  margin: 0;
}
dt.long-dt {
  flex-basis: 100%;
}
dt.long-dt + dd {
  flex-basis: 100%;
  padding-left: 10em;
}                
<dl>
  <dt>one</dt>
  <dd>one</dd>
  <dt class="long-dt">two that is longer</dt>
  <dd>two only moves down because I manually told it to in the CSS</dd>
  <dt>three</dt>
  <dd>three</dd>
</dl>

I can think of a couple of other solutions, but none that work cleanly without manually doing stuff for the longer <dt> elements.

How can I achieve this layout in CSS? I'm happy to change the HTML so long as it's reasonably semantic.


Solution

  • Here's a solution that uses no flex, but floats, clear-both and min-width for the dts and calc(100% - [min-width of dt]) for the width of the dds:

    dt {
      min-width: 5em;
      white-space: nowrap;
      clear: both;
      float: left;
    }
    dd {
      margin: 0;
      width: calc(100% - 5em);
      float: right;
    }
    <dl>
      <dt>one</dt>
      <dd>one</dd>
      <dt>two that is longer</dt>
      <dd>two moves down without having to manually tell it to in the CSS</dd>
      <dt>three</dt>
      <dd>three</dd>
      <dt>four which is also longer</dt>
      <dd>four dd which is even longer and has to wrap into two lines, at least on rather narrow screens or in narrow parent elements. It also moves down without having to manually tell it to in the CSS</dd>
      <dt>five</dt>
      <dd>five</dd>
    </dl>