2

So for specific reasons I'm trying to use the dl (Description List) html element. I wanted the elements contents to display each dt and dd on their own row which I accomplished as such..

div {
  padding: 1rem;
  color: #fff;
  background-color: rgba(0,0,0,.8);
}
  
dl dt, dl dd {
  display: inline;
  line-height: 1.75rem;
}
<div>
  <h3>Cryptids of Cornwall:</h3>
  <dl>
      <dt>Beast of Bodmin</dt>
      <dd>A large feline inhabiting Bodmin Moor.<br></dd>

      <dt>Morgawr</dt>
      <dd>A sea serpent.<br></dd>

      <dt>Owlman</dt>
      <dd>A giant owl-like creature.<br></dd>
  </dl>
</div>

Which is really close to what I'm after, but I'm wondering if anyone knows a way with maybe Flex or Grid for a more uniformed layout like a table while still using the dl the element so the output is more like this...

table {
  border-collapse: collapse;
  color: #fff;
  background-color: rgba(0,0,0,.8);
}

table th {
  text-align: left;
  padding-left: 1rem;
}

table td {
  padding: 1rem;
}

table tr td:first-of-type {
  text-align: right;
  border-right: lightgray 1px solid;
}
<table>
  <tr>
    <th colspan="2">
      <h3>Cryptids of Cornwall:</h3>
    </th>
  </tr>
  <tr>
      <td>Beast of Bodmin</td>
      <td>A large feline inhabiting Bodmin Moor.</td>
  </tr>
  <tr>
      <td>Morgawr</td>
      <td>A sea serpent.</td>
  </tr>
  <tr>
      <td>Owlman</td>
      <td>A giant owl-like creature.</td>
  </tr>
</table>

Is there a way to accomplish this with css and explicitly using the dl element? I've tried things display: table on the parent dl with the dt and dd as display: table-cell but then I can't seem to break the into new rows after the dd along with failed attempts at using flex and css grid so wondering if someone knows a trick to teach? Thanks!

CuriousG
  • 97
  • 6
  • BTW, you should use child-selectors instead of descendant selectors: `dl > dt` and `dl > dd` instead of `dl dt` and `dl dd` - that way if you have nested `
    ` elements things won't break.
    – Dai Apr 13 '22 at 03:55
  • Will you ever have a `
    ` with zero, or 2 or more `
    ` next-siblings? Or will each `
    ` always have exactly one next-sibling `
    `?
    – Dai Apr 13 '22 at 03:58
  • @Dai Nah it will only ever be 1:1 with dt:dd per row. As for the selectors ya I agree but it was just a super quick PoC example for the question. Will be reviewing the answers here shortly when a get a free moment. – CuriousG Apr 13 '22 at 13:34

2 Answers2

2

Here's a quick-and-dirty display: grid; implementation:

  • The vertical tracks ("columns") are 1fr 1fr, so they're both 50% wide. I'm unsure of the best approach to make the tracks sized-to-content.
    • I ultimately got this working by simply doing grid-template-columns: auto auto;, phew!
  • There's no white border between the vertical tracks.
    • I did try to hack it by using dl::before (making it 1px wide with a border: 1px solid white but it seems like it's currently impossible to make a grid item span all horizontal tracks when there are implicit tracks.
    • UPDATE: After being inspired by this post, I was able to hack a vertical line by using an absolutely-positioned ::after element (in the <dt> so it has the correct horizontal position without an explicit left or right value).
  • To my surprise, it does actually work very well when a <dt> element has multiple <dd> siblings (I've added one for the Mermaid of Zennor as an example). I was originally apprehensive that multiple <dd> elements would break the layout.
  • BTW, you don't need the <br /> breaks in your HTML. I've removed them in my example below.

div {
  padding: 1rem;
  color: #fff;
  background-color: #333;
}
  
dl, dt, dd {
  margin: 0;
  padding: 0;
}
  
dl {
  color: #eee;
  background-color: #666;
  border-radius: 5px;
  padding: 1rem;
  
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-columns: auto auto;
  grid-template-columns: auto 5px auto;
  grid-template-rows: auto [last-line];
  grid-auto-rows: min-content;
  
  grid-gap: 1rem;
  
  /* This is to allow the `dl > dt:first-child::after` to fill the height */
  position: relative;
}

/* Using this to make a vertical line won't work, see https://stackoverflow.com/questions/44052336/make-a-grid-item-span-to-the-last-row-column-in-implicit-grid
dl::before {
  content: '';
  display: block;
  grid-column-start: 2;
  grid-column-end: 3;
  grid-row-start: 1;
  grid-row-end: -1;
  grid-row-end: last-line;
  
  background-color: red;
  border-left: 1px solid white;
  width: 1px;
}
*/

dl > dt:first-child::after {
  content: '';
  display: inline;
  border-left: 1px solid white;
  width: 1px;
  
  position: absolute;
  top: 0;
  bottom: 0;
  /* Offset it to the right a bit using margin: */
  margin-left: 1rem;
}

dl > dt {
  grid-column-start: 1;
  grid-column-end: 2;

  /*
  `align-self` is for vertical alignment in a grid cell.
  `justify-self` is for horizontal alignment in a grid cell.
  */

  align-self: center; 
  justify-self: end; /* i.e. right-align */
  text-align: right; /* This is needed so narrow-viewports don't break. */
}
dl > dd {
  grid-column-start: 2;
  grid-column-end: 3;
  
  grid-column-start: 3;
  grid-column-end: 4;

  align-self: center; 
  justify-self: start; /* i.e. left-align */
}
<div>
  <h3>Cryptids of Cornwall:</h3>
  <dl>
      
      <dt>Beast of Bodmin</dt>
      <dd>A large feline inhabiting Bodmin Moor.</dd>

      <dt>Morgawr</dt>
      <dd>A sea serpent.</dd>

      <dt>Mermaid of Zennor</dt>
      <dd>A popular Cornish folk tale</dd>
      <dd>The parishioners at St. Senara's commemorated the story by having one end of a bench carved in the shape of a mermaid</dd>

      <dt>Owlman</dt>
      <dd>A giant owl-like creature.</dd>

      
  </dl>
</div>

Screenshot proof:

It looks good at a variety of viewport sizes:

Very narrow:

enter image description here

Normal

enter image description here

Very wide

enter image description here

Dai
  • 141,631
  • 28
  • 261
  • 374
1

I've tried things display: table on the parent dl with the dt and dd as display: table-cell but then I can't seem to break the into new rows after the dd along with failed attempts at using flex and css grid so wondering if someone knows a trick to teach?

Table cells need table rows, and table rows need a table (technically a tbody, thead, or tfoot). Originally I thought that the <dl>, <dt>, and <dd> were not fit to configure into a table/grid layout since <dl> was the only parent element, not even <dt> was allowed to have <dt> and <dd> as children. Then I found out that <div> is valid if a direct descendant of a <dl> which is the perfect position to be a table row.

If you want table behavior, assign display table type values:

Element Property Value Hierarchy
<dl> display table
<dt> display table-caption dl > dt
<div> display table-row dl > div
<dt> diaplay table-cell dl > div > dt
<dd> display table-cell dl > div > dd

A <div> can be a direct descendant (ie child) of a <dl> and a parent of <dt> and <dd>

Using <table> and table component elements for layout has been discouraged for years, but not display: table and associated values.

html {
  font: 2ch/1.75 'Garamond'
}

main {
  padding: 1rem;
  color: #fff;
  background-color: rgba(0, 0, 0, .8);
}

dl {
  display: table;
  table-layout: fixed;
  border-collapse: collapse;
  width: 80%;
}

dl>dt {
  display: table-caption;
  width: 100%;
  margin-bottom: 5px;
  padding: 0;
  border: 0;
  font-size: 1.17rem;
  font-weight: 900;
}

dl>div {
  display: table-row;
}

dl>div:first-of-type>dt {
  width: 50%;
}

dl>div:first-of-type>dd {
  width: 50%;
}

div>dt,
div>dd {
  display: table-cell;
}

div>dt {
  padding-right: 10px;
  border-right: 2px solid #fff;
  text-align: right;
}

div>dd {
  padding-left: 10px;
  border-left: 2px solid #fff;
}
<main>
  <dl>
    <dt>Cryptids of Cornwall:</dt>
    <div>
      <dt>Beast of Bodmin</dt>
      <dd>A large feline inhabiting Bodmin Moor.</dd>
    </div>
    <div>
      <dt>Morgawr</dt>
      <dd>A sea serpent.</dd>
    </div>
    <div>
      <dt>Owlman</dt>
      <dd>A giant owl-like creature.</dd>
    </div>
  </dl>
</main>
zer00ne
  • 41,936
  • 6
  • 41
  • 68
  • Clever approach but the containing child divs would break the semantics compliance. Still definitely worth an upvote though! – CuriousG Apr 13 '22 at 18:25
  • That's what I thought at first, go here: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl , then ctrl+f and enter: *permitted content* . In [WHATWG](https://developer.mozilla.org/en-US/docs/Glossary/WHATWG) HTML, [W3C](https://developer.mozilla.org/en-US/docs/Glossary/W3C) HTML 5.2 and later `
    ` is allowed to be a child of `
    `. Complying explicitly with standards is being in compliance semantically.
    – zer00ne Apr 13 '22 at 21:12
  • Yea I saw that too but I questioned it against the [w3c permitted content](https://www.w3.org/TR/2012/WD-html-markup-20121025/dl.html) spec, figured better safe than sorry but that's an excellent point! :) – CuriousG Apr 13 '22 at 21:21
  • That's a link to a version published 10 years ago. Here's a link to the version updated yesterday: https://html.spec.whatwg.org/multipage/grouping-content.html#the-dl-element. Also, the article in MDN verbatim: *" In WHATWG HTML, **W3C HTML 5.2 and later**..."* `
    ` was added as a permitted content because `
    ` lacked any sub-containers.
    – zer00ne Apr 13 '22 at 21:55
  • Yea you're totally right, this line confirms it especially **"In order to annotate groups with microdata attributes, or other global attributes that apply to whole groups, or just for styling purposes, each group in a dl element can be wrapped in a div element. This does not change the semantics of the dl element."** so they're definitely both correct answers with contemporary spec applied though Dai's answer keeps the node flow easier for generation and traversing with javascript which is more applicable to my specific scenario. However like I said, both are definitely correct! – CuriousG Apr 13 '22 at 22:16
  • IMO, using a `
    ` in a `
    ` looks vulgar, but I posted the solution since it resolves the question without violating standards or semantics.
    – zer00ne Apr 13 '22 at 22:29