Alex
Alex

Reputation: 335

How can I style a definition list like a table?

I am trying to create a <dl> that has the appearance of a 2 column table, but am having some trouble getting the styling correct and would love some feedback!

This is the mockup of what I am trying to accomplish: mockup

Here is a codepen of my attempts so far.

my markup is a standard <dl> where there can be multiple <dt>s for a <dd> or multiple <dd>'s for a <dt>.

<dl class="b-references">
  <dt class="b-references__term">Director</dt>
    <dd class="b-references__item">Edgar Wright</dd>
  <dt class="b-references__term">Cast</dt>
    <dd class="b-references__item">Ansel Elgort</dd>
    <dd class="b-references__item">Lily James</dd>
    <dd class="b-references__item">Jon Hamm</dd>
    <dd class="b-references__item">Jamie Foxx</dd>
    <dd class="b-references__item">Kevin Spacy</dd>
    <dd class="b-references__item">Elza Gonzalez</dd>
    <dd class="b-references__item">Jon Bernthal</dd>
</dl>

and here is as close as I could get with the styles (SCSS):

.b-references {
  border: 1px solid color(neutral, light);
  overflow: auto;
  position: relative;

  &__term {
    clear: both;
    float: left;
    display: inline-block;
    font-weight: font-weight(bold);
    padding: 1rem;
    min-width: 16rem;
    border-right: 1px solid color(neutral, light);

    &:not(:first-child):after {
      content: '';
      position: absolute;
      top: 1rem;
      left: 0;
      right: 0;
      border-top: 1px solid color(neutral, light);
    }
  }

  &__item {
    float: left;
    padding: 1rem 0;

    &:after {
      content: ',';
      margin-right: .25rem;
    }

    .b-references__term + & {
      content: '';
    }

    dt + & {
      padding-left: 1rem;
    }
  }
}

There is a few problems with this approach though:

  1. If a set's <dd>'s exceed the width given, they break to the next line and fall under the <dt> not the other <dd>'s.
  2. I can't figure out a way to remove the comma from the last <dd> in each set. I can't target it by checking if it is followed by a <dt>.
  3. If there are multiple <dt>'s for a set, I'm not sure how to define the styles so all of them are comma separated within the same "cell" like the mockup.

working version

I'm assuming many solutions will involved simply using a table, but semantically a dl makes much more sense, so I'd like to try to get this to work if I can. Any help is much appreciated!

.b-references {
  border: 1px solid color(neutral, light);
  overflow: auto;
  position: relative;
}

.b-references__term {
  clear: both;
  float: left;
  display: inline-block;
  font-weight: font-weight(bold);
  padding: 1rem;
  min-width: 16rem;
  border-right: 1px solid color(neutral, light);
}

.b-references__term:not(:first-child):after {
  content: '';
  position: absolute;
  top: 1rem;
  left: 0;
  right: 0;
  border-top: 1px solid color(neutral, light);
}

.b-references__item {
  float: left;
  padding: 1rem 0;
}

.b-references__item:after {
  content: ',';
  margin-right: .25rem;
}

.b-references__term+.b-references__item {
  content: '';
}

dt+.b-references__item {
  padding-left: 1rem;
}
<dl class="b-references">
  <dt class="b-references__term">Director</dt>
  <dd class="b-references__item">Edgar Wright</dd>
  <dt class="b-references__term">Cast</dt>
  <dd class="b-references__item">Ansel Elgort</dd>
  <dd class="b-references__item">Lily James</dd>
  <dd class="b-references__item">Jon Hamm</dd>
  <dd class="b-references__item">Jamie Foxx</dd>
  <dd class="b-references__item">Kevin Spacy</dd>
  <dd class="b-references__item">Elza Gonzalez</dd>
  <dd class="b-references__item">Jon Bernthal</dd>
</dl>

Upvotes: 0

Views: 1749

Answers (1)

Lucas
Lucas

Reputation: 423

Here is an answer if you're able to use CSS3 grids.

The only thing this requires are pairs of <dt> & <dd>, and nesting elements inside of the <dd> into another list.

With this approach, you're free to style the list of directors/cast independent of the <dl>.
Here, I used CSS to make it look like a bunch of comma separated names.

.b-references {
  border: 1px solid lightgray;
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.b-references__term,
.b-references__item {
  border-bottom: 1px solid lightgray;
  padding: 20px;
}

.b-references__term:last-of-type,
.b-references__item:last-of-type {
  border-bottom: none;
}

.b-references__term {
  font-weight: bold;
}

.b-references__item {
  border-left: 1px solid lightgray;
  margin-left: 0;
}

.comma-separated-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.comma-separated-list>li {
  display: inline;
}

.comma-separated-list>li::after {
  content: ", ";
}

.comma-separated-list>li:last-of-type::after {
  content: "";
}
<dl class="b-references">
  <dt class="b-references__term">
    <ul class="comma-separated-list">
      <li>Director</li>
      <li>Writer</li>
    </ul>
  </dt>
  <dd class="b-references__item">
    <ul class="comma-separated-list">
      <li>Edgar Wright</li>
    </ul>
  </dd>
  <dt class="b-references__term">
    <ul class="comma-separated-list">
      <li>Cast</li>
    </ul>
  </dt>
  <dd class="b-references__item">
    <ul class="comma-separated-list">
      <li>Ansel Elgort</li>
      <li>Lily James</li>
      <li>Jon Hamm</li>
      <li>Jamie Foxx</li>
      <li>Kevin Spacy</li>
      <li>Elza Gonzalez</li>
      <li>Jon Bernthal</li>
    </ul>
  </dd>
</dl>

Edit: Wrapped dt contents into a list too, and added a special list class for comma-separated lists.

Upvotes: 1

Related Questions