CSS の white-space: nowrap; + HTML の wbr 要素 + 日本語コンテンツの組み合わせで起きる問題を回避する

CSS の white-space: nowrap;
HTML の <wbr> 要素の組み合わせによる挙動が
Firefox と Google Chrome で違ってて、
特に日本語コンテンツの表示を統一しようとすると何かとややこしいので
その回避方法を書いてみます。

その前にちょっと前提のお話を。

white-space: nowrap; のおさらい

CSS を書く人には説明の必要もないと思うんだけど、
white-space というのは HTML の要素内で
ホワイトスペース(スペース文字や改行コードなど)がどのように扱われるかを指示するための
CSS のプロパティですね。

W3C による勧告はこちら。

値と指示内容は例えばこんな具合で

normal
連続したホワイトスペースはひとつにまとめる。行ボックスがいっぱいになったら改行する。
pre
連続したホワイトスペースはまとめずに表示する。改行文字が与えられている箇所で改行する。

そして nowrap の場合は

nowrap
ホワイトスペースの扱いは normal と同じ。ただしテキスト内の改行は行わない。

要するに white-space: nowrap;
行ボックスを越えても改行をしたくないところで使うやつですね。

<wbr> のおさらい

HTML の <wbr> 要素は、ざっくり言うと
「改行するならこの位置でね」と指定するものですね。

以前は一部のブラウザで独自実装されてたものだと思うんだけど
HTML5 で正式に復活したやつ。

これは日本語と英語でちょっと事情の違うところ。

英語の場合

英語の単語をブラウザで表示するとき、
幅指定のある要素内にその幅を超えるような長い単語が入ると
入りきらずにはみ出しますね。

pneumonoultramicroscopicsilicovolcanoconiosis

この問題を解決するのに <wbr> が使えます。

<br> だと必ず改行されるけど、
<wbr> は「必要なときだけここで改行」なので
幅に収まるならそのまま、収まらなければ改行という挙動になります。

pneumonoultramicroscopicsilicovolcanoconiosis

日本語の場合

日本語の場合、どんなに長い単語でも
ブラウザではそれぞれの文字がひと単語扱いになるので
幅いっぱいになったら勝手に改行されます。

寿限無寿限無五劫の擦り切れ海砂利水魚の水行末雲来末風来末食う寝る処に住む処藪ら柑子の藪柑子パイポパイポパイポのシューリンガンシューリンガンのグーリンダイグーリンダイのポンポコピーのポンポコナーの長久命の長助

このため、日本語でそのまま <wbr> を使うことは少ないかもしれない。

日本語で white-space: nowrap;<wbr> を組み合わせたい状況

幅指定のある要素の中にテキストを書くとき
ここでは改行してほしくない、ということがあると思います。

たとえば人の名前を並べて「、」で区切るときなど
できれば人名の途中では改行せず
改行するなら「、」の後で、というふうにしたい。

改行をしない指定

これは前述の white-space: nowrap; を使うだけですね。

改行したい箇所の指定

これも前述の <wbr> でいけるはず。

ところがそれを素直に使ってもなかなかうまくいきません。

ブラウザによって実装が違う

white-space: nowrap; の要素内に <wbr> を入れてみる

素直に書くとこれでいけそうです。

<!DOCTYPE html>
<meta charset="UTF-8">
<title>wbr を入れるよ</title>
<style>
  p {
    width: 300px;
    white-space: nowrap;
  }
</style>

<p>新原 雅司、<wbr>原田 康生、<wbr>小山 哲志、<wbr>田中 久輝、<wbr>保科 一成、<wbr>大村 創太郎、<wbr>増永 玲</p>

ところがこれは Google Chrome や Safari など
WebKit のブラウザでは期待どおりの結果になるんだけど
Firefox だとうまくいかない。

どうも Firefox では
white-space: nowrap; 指定された要素の中で
<wbr> を使っても無視されるようです。

このことはだいぶ前にフォーラムでも議論されてるんだけど

<wbr>white-space: nowrap; の指定を回避するという実装について
あまり前向きな話にはなってないみたい。

確かに、英語では必要ないと思います。
英語なら普通に書けば単語の途中で改行されることがなく
単語と単語の間にスペースがあってそこが改行候補になるから。

ちょっと他の言語のことも考えてほしいんだけど
2年以上前の議論のままになっていることを考えると
なかなか変わらないかもしれない。

white-space: nowrap; の要素を複数並べてみる

代わりに、こう書いてみました。

<!DOCTYPE html>
<meta charset="UTF-8">
<title>span で括ってみるよ</title>
<style>
  p {
    width: 300px;
  }
  span {
    white-space: nowrap;    
  }
</style>

<p><span>新原 雅司、</span><span>原田 康生、</span><span>小山 哲志、</span><span>田中 久輝、</span><span>保科 一成、</span><span>大村 創太郎、</span><span>増永 玲</p>

改行したくない語句のかたまりを <span> で括って
それらに white-space: nowrap; を指定。

ところが今度は逆の結果で、
Firefox だと期待どおりなのに
Google Chrome では改行が入らない。

Google Chrome は、white-space: nowrap; のインライン要素が連続する場合
要素の切れ目は考慮してくれないようです。

解決策

どちらのブラウザでも期待どおりになるやり方が2通りあったので書いてみます。

<span> の間に <wbr>

<!DOCTYPE html>
<meta charset="UTF-8">
<title>span と wbr を両方使う</title>
<style>
  p {
    width: 300px;
  }
  span {
    white-space: nowrap;    
  }
</style>

<p><span>新原 雅司、</span><wbr><span>原田 康生、</span><wbr><span>小山 哲志、</span><wbr><span>田中 久輝、</span><wbr><span>保科 一成、</span><wbr><span>大村 創太郎、</span><wbr><span>増永 玲</p>

white-space: nowrap; を指定した <span> を並べても
Google Chrome が改行を入れてくれないので
もう <span> の間に <wbr> を入れちゃう。
これならどっちのブラウザでも期待どおりの表示になりました。

display: inline-block; を並べる

さっきのはどうも無理矢理感が激しいので
余計な要素を入れずに何とかしたい。

display: inline-block; でできました。

<!DOCTYPE html>
<meta charset="UTF-8">
<title>inline-block にしてみる</title>
<style>
  p {
    width: 300px;
  }
  span {
    white-space: nowrap;
    display: inline-block;
  }
</style>

<p><span>新原 雅司、</span><span>原田 康生、</span><span>小山 哲志、</span><span>田中 久輝、</span><span>保科 一成、</span><span>大村 創太郎、</span><span>増永 玲</p>

Google Chrome は
white-space: nowrap;<span> の間で改行してくれないけど、
<span>display: inline-block; が指定されていると
期待どおりに改行してくれました。

というわけで、今回の結論としては

日本語コンテンツで改行したくない部分と改行の候補を示す場合、改行したくない部分を <span> などのインライン要素で括り

white-space: nowrap;
display: inline-block;

を指定する

ということになりそうです。

こんだけ書いといて

何かだいぶいろいろ書いたんだけど、
こんだけ書いといて記事を公開してみたら
「え、それこうすれば一発でできるけど」
と指摘されることもよくあります。

教えてほしいような、そっとしといてほしいような。

  • このエントリーをはてなブックマークに追加