cssだけで、未知の行数のテキストをボックスに対して上下中央、更に特定行数だけ頭出しする


概要

最近、

<p class="hoge">テキストテキスト</div>

こんな感じの非常にシンプルな構造のときに、cssのみで

  • 中のテキストの行数は未知のとき、このテキストをボックスに対して上下中央にしたい
  • ある行数(ex. 2行)を超えたら最初の2行だけを頭出しで上下中央に表示したい

こんな感じ↓

というような欲張りな要求をされる場面に出会ってしまい、ちょっと悩んだのですがなんとか解決できたので書いてみます。

解決するcss

わかりやすいようにscssっぽく書いています。

$max-lines: 2;
$vertical-padding: 10px;
$font-size: 16px;
$line-height: $font-size * 1.4;

.hoge {
  width: 200px;
  height: $max-lines * $line-height; /* 実際の高さは +($vertical-padding * 2) になることに注意 */
  font-size: $font-size;
  line-height: $line-height;
  border-width: $vertical-padding 0;
  border-color: transparent;
  border-style: solid;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.hoge:before, 
.hoge:after {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
}

ポイントは、

  • 疑似要素と、flexが残った隙間を埋めてくれることを利用し上下中央を実現している
  • transparentなborderを使って上下のpaddingを作る
  • borderだと、overflowを使って指定行数以上の表示をカットすることができる

というところです。

普通はtable-cellvertical-alignを使ってしまうところですが、このようなスタイルであれば、レイアウトのために1個タグが増えてしまう問題を解決できます。また、疑似要素とflexを使って上下中央を実現するのは珍しいのではないかと思い、記事化してみました。コメントでも書いているとおり、高さ計算がちょっと素直じゃないことに注意です。(box-sizing: border-box でも素直にはならない)