I have some HTML structure like this:
<ul>
<li>
<h2>Item 1</h2>
<dl>
<div><dt>attr1</dt><dd>value a</dd></div>
<div><dt>attr2</dt><dd>value b</dd></div>
<div><dt>attr3</dt><dd>value c</dd></div>
</dl>
</li>
<li>
<h2>Item Another One Here</h2>
<dl>
<div><dt>attr1</dt><dd>value x</dd></div>
<div><dt>attr2</dt><dd>value some bit long</dd></div>
<div><dt>attr3</dt><dd>value z</dd></div>
</dl>
</li>
</ul>
I want it be rendered as:
---------------------------------------------------------------------
Item 1
attr 1: value a attr 2: value b attr 3: value c
---------------------------------------------------------------------
Item Another One Here
attr 1: value x attr 2: value some bit long attr 3: value z
---------------------------------------------------------------------
Attributes are aligned to each other based on the length of theirs contents.
How can I do that?
I would avoid change my markup to <table>
, since they are not really tables. I had tried layout them using display: table-*
, but that won't work for the title (which should take place of whole row instead of one cell).
This layout is possible with the CSS Grid Layout Module
.container {
display: inline-grid;
grid-column-gap: 1em;
grid-template-columns: repeat(3,auto);
padding: 0;
background-color: white;
padding-bottom: 0.5em;
border-bottom: 2px dashed;
}
.container li, .container dl {
display: contents;
}
h2 {
grid-column: 1 / -1;
font-size: inherit;
padding: 0.5em 0 0 0;
border-top: 2px dashed;
}
dl > div, dd, dt {
display: inline-block;
padding: 0;
margin: 0;
}
dt:after {
content: ':'
}
dd {
margin-left: 0.5em;
}
dl > div:nth-child(1) {
background-color: lightblue;
}
dl > div:nth-child(2) {
background-color: lightgreen;
}
dl > div:nth-child(3) {
background-color: pink;
}
<ul class="container">
<li>
<h2>Item 1</h2>
<dl>
<div><dt>attr1</dt>
<dd>value a</dd>
</div>
<div><dt>attr2</dt>
<dd>value b</dd>
</div>
<div><dt>attr3</dt>
<dd>value c</dd>
</div>
</dl>
</li>
<li>
<h2>Item 2 - Another One Here</h2>
<dl>
<div><dt>attr1</dt>
<dd>value y -bla bla </dd>
</div>
<div><dt>attr2</dt>
<dd>value some bit long</dd>
</div>
<div><dt>attr3</dt>
<dd>value z</dd>
</div>
</dl>
</li>
<li>
<h2>Item 3 - Another One Here</h2>
<dl>
<div><dt>attr1</dt>
<dd>value x</dd>
</div>
<div><dt>attr2</dt>
<dd>value some much longer</dd>
</div>
<div><dt>attr3</dt>
<dd>value z - blabl bla</dd>
</div>
</dl>
</li>
</ul>
The difficulty here is since the li
and dl
elements aren't direct children of the grid container - you can't apply grid properties to it.
Grid Layout Module Level 2 - Subgrids (currently a draft spec) are supposed to solve this problem, but in the meantime we can use display:contents
to overcome this.
See this post for more details.
If your markup was flat to begin with, then you wouldn't need display: contents
and CSS grid module could do this fine:
.container {
display: inline-grid;
grid-column-gap: 1em;
grid-template-columns: repeat(3,auto);
padding: 0;
background-color: white;
padding-bottom: 0.5em;
border-bottom: 2px dashed;
}
h2 {
grid-column: 1 / -1;
font-size: inherit;
padding: 0.5em 0 0 0;
border-top: 2px dashed;
}
dl, dt, dd {
display: inline-block;
padding: 0;
margin: 0;
}
dt:after {
content: ':'
}
dd {
margin-left: 0.5em;
}
dl:nth-of-type(3n + 1) {
background-color: lightblue;
}
dl:nth-of-type(3n + 2) {
background-color: lightgreen;
}
dl:nth-of-type(3n) {
background-color: pink;
}
<div class="container">
<h2>Item 1</h2>
<dl><dt>attr1</dt><dd>value a</dd></dl>
<dl><dt>attr2</dt><dd>value b</dd></dl>
<dl><dt>attr3</dt><dd>value c</dd></dl>
<h2>Item 2 - Another One Here</h2>
<dl><dt>attr1</dt><dd>value x</dd></dl>
<dl><dt>attr2</dt><dd>value some bit long</dd></dl>
<dl><dt>attr3</dt><dd>value z</dd></dl>
<h2>Item 3 - Another One Here</h2>
<dl><dt>attr1</dt><dd>value x</dd></dl>
<dl><dt>attr2</dt><dd>value some much much much longer</dd></dl>
<dl><dt>attr3</dt><dd>value z</dd></dl>
</div>
NB:
In order to 'shrink-wrap' the grid I applied display: inline-grid
to the grid container.