Skip to contentKyle Macquarrie

Styling a Description List with CSS Grid

An underrated HTML element is the <dl> description list, ideal for doing key: value style lists of things when a one-dimensional <ul> doesn’t quite cut it.

It consists of a description list <dl> tag, which contains <dt> (description term) and <dd> (description details), most often in matched pairs which is what we’ll deal with here.

When styling a list like this, you often want some kind of visual layout that looks something like a table; however, since there’s no wrapper element for each key/value pair (like a <tr> table row element), this has historically not been so simple. Fortunately, with CSS Grid this becomes much simpler. (Technically you can use a <div> to wrap each key/value group, but now we don’t have to!)

Here’s the HTML we’ll be styling:

<dl>
  <dt>description title</dt>
  <dd>description data</dd>
  <dt>short</dt>
  <dd>short data</dd>
  <dt>A long title that takes up more space</dt>
  <dd>short</dd>
</dl>

And some basic styling:

dl,
dt,
dd {
  border: 1px dotted currentColor;
}

dt,
dd {
  padding: 0.25em;
}

dt::after {
  /* gives us a title: description format  */
  content: ':';
}

Default layout

Without any extra styling, everything has display: block by default. The : we added as a pseudo-element and the browser default indentation on the description details are the only visual indication of how the items relate to each other. So far, so brutalist.

description title
description data
short
short data
A long title that takes up more space
short

Old Style Floats

We can tidy that up a bit using floats to give us a table row type layout, but the <dt>s all have different sizes, so the alignment of items looks a bit random; it’s not easy to scan the list quickly. You also have to do some kind of clearfix or risk other bits of the layout going a bit mad.

You could tidy it up a bit by fixing the width of the <dt> but it’s always going to be a compromise, especially if you don’t know what data you’re going to be dealing with ahead of time.

dl {
  overflow: hidden; /* clearfix hack */
}

dd {
  margin: 0; /* remove browser default margin */
}

dt,
dd {
  float: left;
}

dt {
  clear: both;
}
description title
description data
short
short data
A long title that takes up more space
short

Modern CSS Grid

With CSS grid, we can get our table-style layout to fully align the titles, without having to hard code a width, using less code, and with less chance of doing something unexpected. auto 1fr sets the first column to fit the content and the second to use all the remaining space in the row. You get responsive behaviour out of the box, without having to special case anything.

dl {
  display: grid;
  grid-template-columns: auto 1fr;
}

dd {
  margin: 0; /* remove browser default margin */
}
description title
description data
short
short data
A long title that takes up more space
short

Being able to nail that layout, without requiring any extra wrapper elements, with just a few lines of CSS would have been unimaginable not very long ago. I’ve not had much cause or opportunity to really dig into CSS Grid properly yet but just this simple use case has really piqued my interest.

← All articles