【CSS】white-space: nowrapとflexが引き起こすデザイン破壊とその対策

今回は文章の改行を制御するCSSプロパティであるwhite-spaceと、近年のCSSではもはや当たり前になっているflexが引き起こす妙な相互作用についてお話します。

まずは少し話が反れますが、white-spaceをよく使用するポイントの紹介から。

# テキストの省略をCSSで実現する

![image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676048/8b55c3d9-dc60-490e-9e8c-2927fee555ee.png)

長い文字列を、「…」などで省略するデザイン、よく見かけますよね。
これは **text-overflow** を使用することでCSSのみで実装が出来ます。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="vEYzKbg" data-pen-title="01" data-user="Sekappy" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/Sekappy/pen/vEYzKbg">
  01</a> by SekappyOfficial (<a href="https://codepen.io/Sekappy">@Sekappy</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>

サンプルにある3つのプロパティ
+ **text-overflow: ellipsis** （領域からはみ出したテキストに省略記号を付ける）
+ **white-space: nowrap**（領域の端までテキストが行っても折り返さない）
+ **overflow: hidden**　（領域のからはみ出した要素を表示しない）

を適用することで、1行に収まらないテキストを省略したデザインを実現することができます。

**text-overflow – CSS: カスケーディングスタイルシート | MDN**
https://developer.mozilla.org/ja/docs/Web/CSS/text-overflow

# flexと合わせて使ってみる
![image-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676048/033680e4-04c7-4eef-a7ba-a2a4dbd697ea.png)

さて本題です。
上記画像のようなデザインを実装したいとしましょう。
先ほど作成したテキスト省略向けの要素を、横並びのflexboxの中に突っ込んでみます。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="zxYJGGd" data-pen-title="02" data-user="Sekappy" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/Sekappy/pen/zxYJGGd">
  02</a> by SekappyOfficial (<a href="https://codepen.io/Sekappy">@Sekappy</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>

サイトのデザインを破壊するレベルで表示が崩れてしまったと思います。
flexである親要素の幅の上限を超えて、子要素の幅が伸びてしまい、要素がはみだしてしまっています。何が起こっているのでしょうか。

# 解決法
まずは解決法から。
flexアイテムに **min-width: 0;** を適用しましょう。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="zxYJBbO" data-pen-title="03" data-user="Sekappy" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/Sekappy/pen/zxYJBbO">
  03</a> by SekappyOfficial (<a href="https://codepen.io/Sekappy">@Sekappy</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>

表示が正常になりました。

# 原因
直接的な原因は、flexアイテムの **min-width: auto** の解釈が通常のブロック要素と異なり、 **内包する要素全てが収まる最小サイズに設定される** ことです。

**min-width – CSS: カスケーディングスタイルシート | MDN**
https://developer.mozilla.org/ja/docs/Web/CSS/min-width#auto

何もしていない場合、要素の **min-width** の初期値は **auto** に設定されます。
また、flexの幅を決めるプロパティである **flex-basis** よりも **min-width** の値が優先されてしまうため、先ほどの現象が発生してしまうわけです。
なので、該当のflexアイテムに対して **min-width: 0** を適用することで、初期値であるmin-width: autoを打ち消し、要素の幅が適切に認識されるわけです。

white-spaceを使用しない場合でも、flexアイテムがflexコンテナを大きくはみ出してしまう状況が発生することがあると思います。
その際には、flexアイテムにmin-width: 0を適用することを試してみてください。

# 参考
**html – white-space: nowrap breaks flexbox layout – Stack Overflow**
https://stackoverflow.com/questions/38223879/white-space-nowrap-breaks-flexbox-layout

**Flexbox からコンテンツはみ出る問題を完全に解決する #HTML – Qiita**
https://qiita.com/mpyw/items/dfc63c1fed5dfc5eda26