24

I am trying to create a list consisting of key-value-pairs where the key is on the left and the values are on the right side one underneath the other.

Authors          John Doe
                 Jane Doe
                 Max Mustermann

Publishers       Johne Doe
                 Jane Doe
                 Max Mustermann

My problem is how do I force a line break between each dd element? I know this would be easy with floating elements, but I was wondering if it's possible to achieve using flexbox only. Unfortunately, by definition, I cannot wrap the dd elements in their own container.

dl {
  display: flex;
}

dt {
  width: 33%;
}

dd {
  margin: 0;
}
<dl>
  <dt>Authors</dt>
  <dd>John Doe</dd>
  <dd>Jane Doe</dd>
  <dd>Max Mustermann</dd>
</dl>

<dl>
  <dt>Publishers</dt>
  <dd>John Doe</dd>
  <dd>Jane Doe</dd>
  <dd>Max Mustermann</dd>
</dl>
kukkuz
  • 41,512
  • 6
  • 59
  • 95
  • Just for the record, I understand that I could simply use one `dd` with multiple `span`s inside or simply use `
    `.
    –  Nov 23 '16 at 11:08
  • 2
    We must start with good HTML structure (**not adapt HTML to the simplest CSS**)... And ideal HTML structure say also some *semantic* about the content. So, with this considerations, this HTML fragment **is "wrong"**, the typical list use only one `
    ` for many pairs of title-descriotion itens. See the answer https://stackoverflow.com/a/50177309/287948
    – Peter Krauss May 04 '18 at 14:56

3 Answers3

34

How about setting flex-wrap on the dl and have a width > 50% for dd along with margin-left: auto?

See demo below:

dl {
  display: flex;
  flex-wrap: wrap;
}
dt {
  width: 33%;
}
dd {
  margin-left: auto;
  width: 66%;
}
<dl>
  <dt>Authors</dt>
  <dd>John Doe</dd>
  <dd>Jane Doe</dd>
  <dd>Max Mustermann</dd>
</dl>

<dl>
  <dt>Publishers</dt>
  <dd>John Doe</dd>
  <dd>Jane Doe</dd>
  <dd>Max Mustermann</dd>
</dl>
kukkuz
  • 41,512
  • 6
  • 59
  • 95
  • 3
    My God, this seems much easier than the overly complicated solution I came up with: https://jsfiddle.net/rqyyvr3x/ –  Nov 23 '16 at 11:19
30

It's been a few years since this was posted but there is definitely a better way to handle this today using display: grid:

dl {
  display: grid;
  grid-template-columns: 33% auto;
}

dt {
  grid-column: 1;
}

dd {
  grid-column: 2;
}
<dl>
  <dt>Authors</dt>
    <dd>John Doe</dd>
    <dd>Jane Doe</dd>
    <dd>Max Mustermann</dd>

  <dt>Publishers</dt>
    <dd>John Doe</dd>
    <dd>Jane Doe</dd>
    <dd>Max Mustermann</dd>
</dl>
Prestaul
  • 83,552
  • 10
  • 84
  • 84
6

NOTE: the question have not a good snippet code of HTML (the bellow is better).
... We must start with good HTML structure (not adapt HTML to the simplest CSS). And ideal HTML structure say also some semantic about the content.


One dl list with all items!

The typical applications of <dl>/(<dt>+<dd>) lists are like <ul>/<li> lists, but using key-value pairs instead bullets.

Only one description list:
<dl>
  <dt>Authors</dt>
    <dd>John Doe</dd>
    <dd>Jane Doe</dd>
    <dd>Max Mustermann</dd>

  <dt>Etc</dt>
    <dd>etc...</dd>

  <dt>Publishers</dt>
    <dd>John Willey</dd>
    <dd>Miramax</dd>
    <dd>Mary Max</dd>
</dl>

Other list, now starting with one descriptor-item:
<dl>
  <dt>Test</dt> <dd>One desscriptor here</dd>
  <dt>Etc</dt> <dd>etc...</dd>
</dl>

In this context the solution commented by @kukkuz is valid, with some adaptations for the case where we have only one dd per dt, as this other JsFiddle.

dl {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
}
dt {
  font-weight: bold;  
  width: 25%;
  padding-top: 1em;  
}
dd {
  display: flex;
  margin: 0;
  padding-top: 1em;
}

dd + dd {
  width: 100%; 
  padding-top: 0;  
}
dt + dd:not(:nth-child(2)),
dt:first-child + dd:nth-child(2) {
  width: 75%;
}
dd + dd::before {
  width: 25%;
  content: "";
  padding-top: 0
}

To really typical and generic (flex) applications, we need to avoid problems with little screens (smarthphones), so put all into a @media block,

@media screen and (min-width: 360px) {
   ... all above CSS here ...
}

@media screen and (max-width: 360px) {
  dt {
    font-weight: bold;  
    width: 33%;
    padding-top: 1em;  
  }
}

See jsfiddle.net/m5qh8g7r.

Peter Krauss
  • 13,174
  • 24
  • 167
  • 304