CSSで文字を「…」で省略する方法|1行はtext-overflow、2行以上はline-clamp、flexの中ではmin-widthを見る
長い文字を「…」で切る書き方は、1行と2行以上で別のプロパティを使う。
どちらも3つのうち1つ欠けると効かない。
flexboxの中で効かないときは、包んでいる要素のmin-widthを見る。MDNの説明をもとに整理しました。
CSSで長い文字を「…」で省略するには、1行なら overflow・white-space・text-overflow の3つ、2行以上なら display・-webkit-box-orient・-webkit-line-clamp の3つを組み合わせる。
どちらも、1つでも欠けると「…」は出ない。
とくに見落としやすいのが、flexbox の中に置いたときに効かなくなるケースで、原因はたいてい min-width だ。
この記事では、MDN の説明をもとに、書き方と、効かないときに見る場所を順番に整理する。
ここに出てくる仕様の説明は、どれも MDN に書いてあることだ。
「僕は〜と思う」と書いたところだけが、僕の意見になる。
1行で「…」にする書き方
まず、いちばんよく使う形から。
カードのタイトルや一覧の見出しを、1行に収めて末尾を「…」にする書き方だ。
.card_title {
overflow: hidden; /* はみ出した分を隠す */
white-space: nowrap; /* 折り返さずに1行で流す */
text-overflow: ellipsis; /* 隠した位置に「…」を出す */
}大事なのは、text-overflow は自分で文字をあふれさせるプロパティではない、という点だ。
MDN にも、あふれを起こすには overflow と white-space を別に指定する必要がある、と書かれている。
つまり、text-overflow: ellipsis; だけを書いても、文字はふつうに折り返されて、「…」の出番は来ない。
効かないときに見る4か所
3行書いたのに「…」が出ないときは、次の順で見ていくと早い。
1. 3つのうち、どれかが欠けていないか
いちばん多いのはこれだと思う。white-space: nowrap; が無いと文字は折り返すし、overflow: hidden; が無いと文字は枠の外へはみ出したまま表示される。
どちらの場合も「…」は出ない。
開発者ツールで、3つとも打ち消し線なしで効いているかを確かめる。
2. 幅が決まらない要素に書いていないか
MDN によると、text-overflow が効くのは、ブロックコンテナからあふれた文字だけだ。a や span のようなインライン要素に直接書いても、枠そのものが文字に合わせて伸びるので、あふれが起きない。display: block; か display: inline-block; にして、width か max-width で幅を決めてやる。
3. flexbox の中で、親が縮んでくれているか
ここが一番わかりにくい。
横並びのカードの中で、タイトルに3行を書いたのに、文字が「…」にならずに枠を押し広げてしまう、という形で出る。
理由は、flex アイテムの min-width の初期値 auto にある。
MDN の説明では、ふつうのブロックなら auto は 0 になるが、flex アイテムでは中身の最小幅(min-content)になる。white-space: nowrap; で1行にした文字は、その1行ぶんがまるごと最小幅になるので、flex アイテムがそれより細く縮めない。
縮めないから、あふれも起きない。
.card {
display: flex;
}
.card_body {
min-width: 0; /* これで中身より細く縮めるようになる */
}直す場所は、「…」を出したい要素そのものではなく、その要素を包んでいる flex アイテムのほうだ。
MDN には、flex アイテムがスクロールコンテナ(overflow が visible 以外)なら自動の最小幅は 0 になる、とも書かれている。
なので、flex アイテム自身に3行を書いた場合は効くのに、その中の子要素に書いた場合だけ効かない、ということが起きる。
僕はこの差がいちばん混乱のもとだと思う。
flex の中で文字が思ったように並ばない話は、flexboxで文字が1文字ずつ改行される話にも書いた。
向きは逆だが、どちらも「flex アイテムがどこまで縮むか」の話だ。
4. input や textarea に書いていないか
入力欄も見落としやすい。
MDN によると、input・textarea・contenteditable のような編集できる要素では、ブラウザは ellipsis を clip として扱うことが多い。
常にそうなるか、フォーカスしたときだけかはブラウザによって違う。
入力中の文字が「…」で隠れてしまうと編集できないので、そういう作りになっている。
2行・3行で「…」にする書き方
記事の抜粋のように、2〜3行までは見せて、その先を「…」にしたいときはこう書く。
.archive_excerpt {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2; /* 2行で切る */
overflow: hidden;
}このサイトの CSS にも、一覧ページの抜粋(.archive_excerpt)をちょうどこの組み合わせで2行に切る指定が入っている。
MDN の説明では、接頭辞つきの -webkit-line-clamp は、display が -webkit-box(か -webkit-inline-box)で、-webkit-box-orient が vertical のときにしか効かない。
この3つは古い書き方として非推奨になっているが、3つを組み合わせたときの動きは仕様で決められていて、今後も使える、とされている。
3つのどれかを消すと、行数の指定ごと効かなくなる。
overflow: hidden; も忘れないほうがいい。
MDN には、これが無いと中身は隠れず、指定した行のあとに「…」だけが出る、と書かれている。
「…」は出たのに、その下に続きの文が見えている、という状態になる。
接頭辞のない line-clamp というプロパティも仕様にはあり、「…」の代わりに好きな文字列を出す書き方まで用意されている。
ただ、対応しているブラウザはまだ限られるので、使う前に MDN の互換性の表で確かめてほしい。
今、手元のサイトで使うなら、僕は上の3点セットを選ぶ。
省略する前に、全文がどこで読めるかを決めておく
最後に、書き方とは別の話をひとつ。
「…」で切った文字は、読む人には見えない。
カードのタイトルなら、クリックした先で全文が読めるので困らない。
でも、切った先にどこにも全文が無い場所で使うと、読む人はその情報にたどり着けなくなる。
なので僕は、「…」を使う場所を決めるときに、全文がどこで読めるかを先に決めるようにしている。
一覧の抜粋なら記事本文、ファイル名なら詳細画面、という具合だ。
全文の行き先が決まらない場所では、省略せずに折り返したほうがいいと思う。
まとめ
- 1行なら
overflow: hidden;・white-space: nowrap;・text-overflow: ellipsis;の3つ - 2行以上なら
display: -webkit-box;・-webkit-box-orient: vertical;・-webkit-line-clampの3つにoverflow: hidden; - 効かないときは、①3つそろっているか ②幅の決まる要素か ③flex アイテムに
min-width: 0;があるか ④入力欄ではないか、の順に見る - 省略する前に、全文が読める場所を決めておく
画像の表示が潰れる話は object-fit の記事に、重なり順の話は z-index が効かない原因の記事に書いた。
どれも「書いたのに効かない」ときに見る場所の話だ。
出典
ほかにも書いています
受託・note・スタンプこういう仕組みを作る相談を受けています
毎日の更新・データ集め・集計の自動化/3万円〜収益がいくらだったか、どの施策が外れたか
note / 個人の視点で掘り下げていますスタンプラリーに挑戦する
行った場所は、現地チェックインで記録に残せます※受託の相談とnoteは、運営者が個人で受けている・書いているものです。
