とろろこんぶろぐ

かけだしR&Dフロントエンジニアの小言

グリッドレイアウト内の要素の横幅の決まり方と三点リーダーを表示させる方法をきちんと理解する

はじめに

Web 開発における CSS のグリッドレイアウトで構成された要素に対して、三点リーダー表示がうまくいかないケースがありました。 今回グリッドレイアウトにおけるグリッドアイテム(グリッドトラック)の横幅の決まり方を勉強したので、備忘のために記事に残しておきます。

サンプルコードはこちらに載せています。

Grid+Ellipsis_example - StackBlitz

三点リーダーはどのように表示するか?

まず、今回対象とする三点リーダーを表示する方法を以下に記載します。

overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
  • overflow: hidden; は、要素の横幅が親の横幅を超えた場合に、横スクロールさせないようにします。
  • text-overflow: ellipsis; は、要素が横にはみ出た分を三点リーダー表示に変える指示になります。
  • white-space: nowrap; は、要素が横にはみ出る際に折り返して二行以上になることを防ぐための指示になります。

これら三つの指示により、中身のコンテンツが要素の横幅を超えて溢れる場合に三点リーダーが表示されます

三点リーダーを作る基礎的なCSS

text-overflow - CSS: カスケーディングスタイルシート | MDN

フローレイアウトにおけるブロック要素の横幅の決まり方

ブロック要素に対して明示的な横幅 (width) の指定がない場合、初期値は auto になります。 また、最小の横幅 min-width も同様に初期値は auto です。

widthauto の場合、親要素の横幅になります。 親要素がない場合(最上位の場合)、要素の横幅はビューポートと同じになります。 つまり、端末やブラウザの横幅と同じになります。

また、この時最小の横幅(min-width)は 0 として処理されます。 言い換えると、この要素は横幅がゼロになるまで短くなり得ます。

ブロック要素の横幅 auto 指定

本来の要素の横幅を超えるようなコンテンツを表示させようとする場合に、 コンテンツは横幅から溢れると判断されて、三点リーダーが表示されることになります。

子要素の横幅から溢れる場合

グリッドレイアウトにおけるブロック要素の横幅の決まり方

グリッドレイアウトは、要素に対して display: grid; のプロパティを指定することで、その子要素を柔軟に並べることができるものです。

この記事ではグリッドレイアウトについては詳細を記述しません。末尾に示す参考文献をご覧ください。

グリッドレイアウトでは、グリッド指定した要素の子要素たちをグリッドアイテムと呼び、暗黙的にグリッドアイテムを並べるためのグリッドトラックが構成されます。

グリッドトラックの横幅のサイズは、明示的に指定されないと auto になります。 しかし、ここでいう autoフローレイアウトにおけるブロック要素で暗黙的に指定されるデフォルト auto とは動きが異なります 。 具体的には以下のルールで最小の横幅が決まります。

グリッドアイテムが、

  1. スクロールコンテナではない
  2. 最小トラックサイズが「auto」なトラック(複数のトラックをまたぐ場合は1つ以上が「auto」なトラック)に配置されている
  3. 複数トラックにまたがって配置されている場合、それらにフレキシブルなトラック(最大トラックサイズを fr で指定したもの)がない

の全ての条件を満たす場合、横幅の最小値 は min-content になります*1

言い換えると、この場合コンテンツの横幅以下にはなりません(つまり要素の横幅を溢れようがない)。

条件を一つでも満たさない場合は、横幅の最小値は 0 になります。 フローレイアウトにおけるブロック要素と一緒の考え方になります。

グリッドアイテムの横幅の決まり方

ちなみに、理由は後述しますがこの要素の配置であれば三点リーダーは意図通りに表示されます。

グリッドレイアウトで子要素の三点が表示されるとき・表示されないとき

表示されない時

ややこしいのですが、以下のようなケースでは三点リーダーが意図通りに表示されません。

  • 一番下の子要素が三点リーダー表示のスタイルを持っている
  • その親の要素は単にブロック要素になっている
  • その親(子から見て祖父母)の要素がグリッドレイアウト指定をしている
  • それぞれ明示的に横幅 (widthgrid-template-columns) を指定していない

三点リーダーが表示されないケース

これは、三点リーダーを表示するはずの要素の親の横幅が自身の横幅と同一になってしまうため、横幅が溢れているという状態にならないためです。

親より上のレイアウトが影響してしまうため、三点リーダーを表示させる要素自体は問題ない場合も多々あります。 その場合例えば Storybook で用意したコンポーネントでは三点リーダーが表示されているが、実際のページ側でグリッドレイアウトで配置されて三点リーダーが表示されなくなる、ということが起きうるので注意が必要です。

表示される時

グリッドレイアウト内の要素の三点リーダーを表示するためには、上記で示したルールを一つでも満たさなければフローレイアウトにおけるブロック要素と同じ条件になるので、三点リーダーが表示されます。

例えば、

  • 親要素にも overflow hidden; を指定してスクロールコンテナにする (図の解決策①)
  • 親のグリッドレイアウト指定で グリッドアイテムの横幅を明示的に指定する (図の解決策②)
    • width や min-width で明示する方法もあるが、grid-template-columns をせっかくなら使いましょう。
    • minmax(0, 1fr) のような記載でも可です。
  • 複数トラックにまたがる場合には、どこかに 1fr を指定しておく

が挙げられます。

三点リーダーを表示させるためには

overflow: hidden; はスクロールできないようにするプロパティなので、直感的にはスクロールコンテナではないと思われるかもしれません。 しかし 仕様上は overflow: hidden; はスクロールコンテナとしてみなされます

CSS Overflow Module Level 3

補足ですが、overflow: clip にすると hidden と同じ効果を得られてかつ、スクロールコンテナではないとみなされます。

overflow - CSS: カスケーディングスタイルシート | MDN

ややこしいのですが、display grid が三点リーダー要素の直接の親になっている場合は、子要素に overflow: hidden; があるのでスクロールコンテナとみなされて、正しく三点リーダーが表示されます。 そのため、上記の「グリッドレイアウトにおけるブロック要素の横幅の決まり方」の例で挙げていた要素の並びでは三点リーダーが表示されていました。

まとめと感想

フローレイアウト、グリッドレイアウトにおける要素の横幅の決まり方、またグリッドレイアウトで三点リーダーを意図通りに表示するために理解すべきことを書きました。

グリッドアイテムのサイズの決まり方を理解するのは動かしながら見てみて、最初は難しかったです。

一見よく分からない挙動に見えるのですが、グリッドと仲良くなれば理解もできるので、今後もグリッドと仲良く頑張ろうと思います。

参考文献と謝辞

グリッドレイアウトは慣れると非常に便利で使いやすい仕組みなので、上記本をぜひ読んでみてください。

※ エビスコムの担当者の方にもコメントをいたたき、大変参考になりました。ありがとうございます。

*1:「作って学ぶ HTML + CSS グリッドレイアウト」から一部引用しています。