Tailwind CSSでスタイリングしているページのレイアウト改善をしていた際に、コンテンツのタイトルが長い場合などは3点リーダー(「...」)で省略するためにtruncate
をタグのクラスにとりあえず追加していたのですが、思うように効かないことがあったため対処法をまとめます。
適用するタグをブロック要素もしくはインラインブロック要素にする
Tailwindのtruncate
クラスは、CSSで言う下記のクラスに当たります。
TextOverflow-TailwindCSS
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
そしてtext-overflow
は、MDNのドキュメントによるとブロックコンテナー要素が適用対象になります。
text-overflow-CSS:カスケーディングスタイルシート|MDN
そのため、たとえばspanタグなどのインライン要素内の文字にtruncate
を適用しようとして<span class="truncate>文字</span>
としても効きません。この場合は、block
もしくはinline-block
を指定してspanタグをブロック要素もしくはインラインブロック要素にすることで反映されます。
適用するタグに一番近い親にflexを指定する
flex
を指定すると直接の子要素はブロック要素のようなものになるらしく、truncate
の適用対象になります。これはAIに聞いてやっとわかりました。以下がAIの回答です。
flexコンテナの直接の子要素(flexitems)は自動的にブロック化されます。つまり:
1. divがflexコンテナになることで
2. その直接の子要素であるspanはflexitemとなり
3. flexitemは自動的にブロックフォーマッティングコンテキスト(BFC)を確立する
4. BFCが確立されることでtext-overflow:ellipsisが有効になる
- display:flexは子要素のレンダリングコンテキストを変更する
- インライン要素でも、flexアイテムになるとブロック的な振る舞いをする
- テキスト切り捨てを確実に機能させるには、要素がブロックコンテキストを持つ必要がある
- これがサンプル3でblockやinline-blockを明示的に指定しなくてもtruncateが機能する理由
挙動をコードで見てみる
tailwindPLAYというサイトでコードを書いて挙動を試してみました。
https://play.tailwindcss.com/CNu1C7kesS
<h1 class="text-2xl">🙅♂️ サンプル1</h1>
<div class="w-2/4 border border-black p-2 text-xl font-bold">
<div>
<span class="truncate"> ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 </span>
</div>
</div>
<div class="h-10"></div>
<h1 class="text-2xl">🙆♂️ サンプル2</h1>
<div class="w-2/4 border border-black p-2 text-xl font-bold">
<div>
<span class="block truncate"> ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 </span>
</div>
</div>
<div class="h-10"></div>
<h1 class="text-2xl">🙆♂️ サンプル3</h1>
<div class="w-2/4 border border-black p-2 text-xl font-bold">
<div class="flex">
<span class="truncate"> ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 </span>
</div>
</div>
<div class="h-10"></div>
<h1 class="text-2xl">🙆♂️ サンプル4</h1>
<div class="w-2/4 border border-black p-2 text-xl font-bold">
<h2 class="truncate"> ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 </span>
</div>
- サンプル1は、spanタグがインライン要素のままなので
truncate
が適用されず、親のdivから文字がはみ出してしまっています。 - サンプル2は、spanタグをブロック要素にしているので
truncate
がきちんと適用されています。 - サンプル3は、親のdivに
flex
を指定しており、その直下の子要素であるspanがすでにブロック要素(のようなもの)になっているため、block
もしくはinline-block
を指定しなくてもtruncate
が適用されます。 - サンプル4は、h2タグがブロック要素のタグであるため、
block
もしくはinline
を指定しなくてもtruncate
の指定のみで適用されます。