折り返し位置を word-break: keep-all で制御する

モダンブラウザでは一通り使える…はず。

サンプル  https://jsfiddle.net/1eczq4r9/8/

## キャッチコピーをいい感じに折り返す

例えばここに[Mackerel](https://mackerel.io/ja/)のキャッチコピーがあります。

```
エンジニアをワクワクさせる「直感的サーバー監視サービス」
```

これを微妙な幅のボックスに入れると、こんな感じに折り返されます。

```
エンジニアをワクワクさせる「直感的サーバー監視サービ
ス」
```

複数行の文章であればベタ組み+禁則処理で十分ではあるのですが、この折り返しはなんだか悔しいですね。中央揃えにするともっと残念な感じです。

```
エンジニアをワクワクさせる「直感的サーバー監視サービ
                       ス」
```

それで `<span>` で囲った上で `display: inline-block` にしたり `<wbr>` を入れたりといった方法が採られてきたわけですが、ここで `word-break: keep-all` が登場します。これを指定すると、文字間の折り返しが禁止されます。

```
<span style="word-break: keep-all">
エンジニアをワクワクさせる「直感的サーバー監視サービス」
</span>
```

```
             エンジニアをワクワクさせる
           「直感的サーバー監視サービス」
```

おおざっぱには文字や数字が連続する時の折り返しを禁止する感じなので、括弧とかが入れば折り返されます。結果的にいい感じになりましたね。

:::note info
**細かい条件について**

> Breaking is forbidden within “words”: implicit soft wrap opportunities between typographic letter units (or other typographic character units belonging to the NU, AL, AI, or ID Unicode line breaking classes [UAX14]) are suppressed, i.e. breaks are prohibited between pairs of such characters (regardless of line-break settings other than anywhere) except where opportunities exist due to dictionary-based breaking.
> https://drafts.csswg.org/css-text-3/#valdef-word-break-keep-all

[UAX#14 で定義される Line Breaking Classes](https://www.unicode.org/reports/tr14/tr14-51.html#Table1) における NU (Number), AL (Alphabetic), AI (Ambiguous), ID (Ideographic) 間の implicit soft wrap opportunities が禁止される、ということですが、このうち AI と ID には、ひらがな・カタカナのほかに絵文字の一部が含まれています。一部というのは、絵文字は EB (Emoji Base) や EM (Emoji Modifier) というクラスも用意されているためです。

例えば下の文章では EB クラスである :+1: の前後だけ keep-all でも分割可能です。この挙動が自然に理解できるかというと、なかなか難しいようにも思います。

```
地球🌏には温泉♨があるので最高👍です
```

ちなみに拗音は CJ (Conditional Japanese Starter) クラスで上記リストにないんですが、分割可能ではありません。UAX#14 側で `Treat as NS or ID for strict or normal breaking.` とあるので、ID 扱いで含まれているんでしょうか。

:::

## 手動で折り返し位置を挿入する

次は記号を含まない短文について考えてみましょう。

```
続きを読むにはわっふるわっふると書き込んでくだ
さい。
```

……まあ別にこれでもいいような気もしますが。

記号類がないので、単純に `word-break: keep-all` を指定すると全く折り返すことができず、ボックスからはみ出してしまいます。スペースや改行を入れる手もありますが、折り返す必要がない場合に余計な隙間ができてしまいます。

そこで [`<wbr>`](https://developer.mozilla.org/ja/docs/Web/HTML/Element/wbr) を使うと、隙間を開けずに折り返し位置を指定できます。

```
<span style="word-break: keep-all">
続きを読むにはわっふるわっふると<wbr>書き込んでください。
</span>
```

```
続きを読むにはわっふるわっふると
書き込んでください。
```

わっふるわっふる。

もしくは見た目に影響しない（余計な隙間を入れない）スペースとして U+200B ZERO WIDTH SPACE を使うのもよいでしょう。

これらのテクニックは CSS Text Module Level 3 でも例示されています。
https://www.w3.org/TR/css-text-3/#jp-title-break


## word-break: keep-all が使える環境

まあだいたいどこでも使えます。

https://caniuse.com/mdn-css_properties_word-break_keep-all

<details>
<summary>古い細かい話</summary>

* IE11: keep-all + 記号の前後の折り返しはOK。[ただし `<wbr>` は使えません。](https://caniuse.com/wbr-element)
    * 似たような働きをする[Unicodeのゼロ幅スペース](https://ja.wikipedia.org/wiki/%E3%82%BC%E3%83%AD%E5%B9%85%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9) `&#8203;` ならIEでも大丈夫。
* EdgeHTML: keep-all + wbr はOK。ただし記号があっても折り返されないようです。
    * ChromiumベースになったEdgeはChromeと同じ
* Firefox: 74以降であれば keep-all + wbr / 記号 どれも使えます
  * 73以前だと記号があっても折り返されないという問題がありました  
  https://bugzilla.mozilla.org/show_bug.cgi?id=1293584
* WebKit, Chrome(Blink): 2015年頃から対応しているようです
  * iOS8以前をターゲットにしなければ大丈夫でしょう

</details>

ちなみに、 `white-space: nowrap` の中で `<wbr>` を使った場合、Chromeでは折り返されますが、Firefoxでは折り返されないようです。<sub> (ref: [bugzilla](https://bugzilla.mozilla.org/show_bug.cgi?id=656960) [crbug](https://bugs.chromium.org/p/chromium/issues/detail?id=923644) [csswg-drafts](https://github.com/w3c/csswg-drafts/issues/3562#issuecomment-458804475))</sub>

## 参考

- https://www.w3.org/TR/css-text-3/#word-break-property
- https://developer.mozilla.org/en-US/docs/Web/CSS/line-break
- http://meta.stackexchange.com/a/91512/286934 元ネタ。