dl要素のcompact表示をCSSで実現する

HTML4の頃に dl要素に compact なる属性があり、それを指定すると

用語
説明文
のような簡潔な形式で表示されるはずだったのだが、残念ながらそれを実装したブラウザはなかった。けれど中国語のスクリプトの表記などでどうしても使いたかったので、dt, dd の表示を変更 - koba::blog の方法でCSSで実現していたのだが、
用語
説明文
長い用語
説明文
のように用語が長い場合に表示がずれてしまって美しくない。これを
用語
説明文
長い用語
説明文
のように表示したいと常々思っていたのだが、やり方を思いついたので実装してみた。

今までの実装

今までの実装はこんな感じ

dt {
    font-weight: bold;
    clear: left; float: left;
    padding-right: 1em;
}
dd {
    margin-left: 4em;
    margin-bottom: 0.5em;
}
dl::after {
    display: block;
    content: '';
    clear: both;
}

dt を浮動要素にして左に寄せ、dd はそれを取り囲むようにするというもの*1。用語が3文字までの場合*2はきれいに表示されるのだが、それ以上になると ddmargin-left4em を超えてしまうので dd の開始位置がずれてしまう。

改良した実装

dd も浮動要素にして右に寄せれば解決できそうだなとは思っていたのだが、dd の幅を決定するうまい方法がなく実現に至らなかった。しかし、CSS3 に関数 calc() が導入され、100% - 4em で実現できるとわかったので試してみた。

dt {
    font-weight: bold;
    clear: both; float: left;   /* clear: both; に変更 */
    padding-right: 1em;
}
dd {
    width: calc(100% - 4em);    /* 幅を決めて */
    float: right;               /* 右に寄せる */
    margin-left: 0;             /* マージンは不要 */
    margin-bottom: 0.5em;
}
dl::after {
    display: block;
    content: '';
    clear: both;
}

このやり方だと dt が長い場合は dd が下に押し出されるので期待通りの表示になる。上手くいった😎

2019-01-06 追記

このやり方では左に回り込んでいる状態で dl が開始されると回り込みが解除されてしまうことが発覚。さてどうしようかな……

*1:dl::after は浮動要素解除のおまじない

*2:中国人の人名はだいたい3文字まで