Web・HTML・CSSのテキスト改行と複数半角スペースの処理に関して

Webで開発をしていてたまに上がってくる問題として、テキストの改行についてあると思います。特にWebサービスのような編集者以外のユーザーがテキストを入力した任意のメッセージなどを表示する場合、改行に関して様々なトラブルが起きたりすることがあります。編集者(作り手側)の場合は適切な箇所で改行タグを入れたり、閲覧者が適切に読めるように文章を改変したりできるのですが、ユーザーにそこまで考慮させるのは難しいことです。

またWebサービスには他にもトラブルの原因となることがあります。Webは様々な環境で閲覧・使用することが可能だということです。PCや携帯、スマートフォン、タブレットなどのデバイスの差異ももちろんありますが、閲覧するソフトウェア(Webブラウザなど)によっても表示のされ方が異なってしまいます。
(できる範囲ではありますが)すべての環境でトラブルなく適切に表示するにはどうしたら良いか?

また近年ではWebアプリケーションでよりネイティブなアプリケーションを作ることも増えてきました。半角スペースを複数連続して入力した場合、Webでは半角スペースを一つとして表示するのが暗黙の了解的になっています。しかし、よりネイティブなアプリケーションを目指したとき、そうも言えない場面もあると思います。
その辺りに関して最近学んだことを書いてみようと思います。

改行のトラブル

改行表示関係でよくあるのはURL文字列が飛び出して表示されてしまうという現象です。

左上の図ではURLが枠内におさまらずに飛び出してしまっています。ローマ字の場合単語の途中で改行されると単語の意味や文章が変わってしまうため、通常改行ポイントになりうるのは半角スペースやハイフンといった記号の後になります。そのため左上の図でも飛び出した後にハイフンの後で改行されていると思います。

これを解決するには「word-wrap:break-word」が有効だと思います。

以下 W3C.orgより(http://www.w3.org/TR/css3-text/#overflow-wrap

‘break-word’
An unbreakable "word" may be broken at an arbitrary point if there are no otherwise-acceptable break points in the line. Shaping characters are still shaped as if the word were not broken, and grapheme clusters must together stay as one unit. No hyphenation character is inserted at the break point.

「word-wrap:break-word」を指定すると、行の中に他に改行ポイントがない場合に限り単語の途中で改行します。 word-wrap プロパティはCSS3のプロパティではありますが、IE6でも使用できるプロパティのようです(検証はしていません)。

display:boxとの併用

「word-wrap:break-word」を指定した要素に「display:box」を指定すると上手く改行されないケースがいくつか確認できました。おそらくブラウザのバグだとは思いますが、現在のところ同時に使用するのは避けるしかなさそうです。(同時に使用するケースがあまりないとは思いますが。Safari6とOpera12は問題なく表示されました。)

Chrome21の場合は微妙に飛び出してしまう。

Firefox11の場合は改行ポイントが発生しなくなって完全に突き抜けてしまいます。

追記(2012.9.4)

「word-wrap:break-word」を指定している要素を包括する要素に「display:box」を指定すれば、表現(表示)的には変わらない感じでできることがわかりました。「word-wrap:break-word」を指定する要素は「display:box」だと上手く計算が行われないことが問題らしいです。

HTMLタグと日本語の禁則処理が合わさった場合の改行トラブル

日本語には禁則処理があり、読点や句読点が改行されて行前に来ないようにしたり、括弧だけが行後・行前に取り残されるというようになっていると思います。この読点や句読点といった記号とHTMLタグを続けてしまうと、変に改行されてしまうといったことがあります。再現するのはSafari6やChrome21といったWebkit系のブラウザです。Mobile Safariでも再現しました。

改行の検証をしています。<span style="font-weight:bold">ワード・ラップ</span>は有効そうです。<br />改行の検証中。どうやら、<span style="font-weight:bold">ワード・ラップ</span>は有効そうです。

上の図をみると明らかに読点や句読点まで入るスペースがあるのに、禁則処理と同じような動作をしています。通常は読点や句読点のあとに改行されるのが自然だと思います(Firefox11やOpera12ではそのように表示されます)。

これに関しては、読点や句読点とHTMLタグの間に半角スペースを入れて対応すればよさそうです。

複数半角スペースの表示

前述でも書いたとおり、Webでは半角スペースを複数続けた場合ひとつに省略して表示するようになっています。Twitterなどで半角スペースを続けて投稿した場合も、内部的には複数半角スペースが存在しますがWebでの表示は半角ひとつぶんに省略されています。

左上の図はWebのtwitter.comで確認したもので、右上の図はTwitterのiPhoneネイティブアプリで確認したものです。ネイティブアプリ上では複数半角スペースを入力した場合も省略されずに表示されているのがわかると思います。(不思議な事にMobile Safariで見られるTwitterのモバイルサイトでは、複数半角スペースは省略され改行は表示されていました。[真ん中の図])
もちろん、すべての環境で同じように表示されなければダメだという話ではありません。

しかし、スマートフォンなどによってネイティブアプリを普段から慣れ親しんでいるユーザーの場合、同じように動作するWebアプリで表示が違うという点に違和感を感じることは考えられます。
また、別の観点としてメモアプリのようなものをWebアプリケーションとして作る場合には、複数半角スペースを入力することも大いに考えられると思います。

このような観点から複数半角スペースを適切に表示する場合は「white-space:pre-wrap」を使用するのが良いと思います(これもIE6で使用できるプロパティです)。「white-space:pre-wrap」を指定すると、連続する複数半角スペースや改行といったものをそのまま表示しますが、ボックスの領域に合わせて改行します。

以下 W3C.orgより(http://www.w3.org/TR/css3-text/#white-space0

‘pre-wrap’
Like ‘pre’, this value preserves white space; but like ‘normal’, it allows wrapping.

white-space:pre-wrapで連続する複数半角スペースが改行されない

ようやく今回のエントリーを書くきっかけになった本題に近づいてきました。
先程も書いた通り、「white-space:pre-wrap」を指定すると連続する複数半角スペースをそのまま表示しますが、ボックスの領域に合わせて改行します。しかし、連続している半角スペースはボックスの領域に達しても改行されないようです。そのため半角スペースがボックスの領域を突き抜けてしまい、ブラウザによっては横スクロールが発生してしまったりします。

Firefox11やOpera12の場合は、左上の図のように半角スペースが突き抜けて存在するため横スクロールが発生しています。Safari6やMobile Safari、Chrome21の場合は右上のようにoverflow:hiddenで隠したような表示になりました。

word-wrap:break-wordとwhite-space:pre-wrapを併用する

最初に書いた改行の問題やpre-wrapによる複数半角スペースの改行問題を解決するために、word-wrap:break-wordとwhite-space:pre-wrapを同時に指定するのが良いと考えました。これによりFirefox11やOpera12でも突き抜けてしまうという問題は解消されます。
しかし、ここでもSafari・ChromeとFirefox・Operaの表示は異なってしまいます。

Firefox・Operaは連続する半角スペースも改行しているのに対し、Safari・Chromeでは改行されずに表示されています。文字を選択してみるとよくわかると思います。
今回、私が思い当たる方法で検証したものとして、これ以上の方法は考えられませんでした。もし、もっと良い方法があるという方はぜひコメントなりで教えてください。

ネイティブアプリケーションの場合

うまく解決できませんでしたと、ここで終わってしまうのも中途半端です。
なので現在使われているネイティブアプリケーションでは、改行や複数半角スペースに関してどのような処理をしているのか調べてみました。

iPhoneのメモアプリ・TwitterアプリなどやMacのMailといったネイティブアプリではSafari6やChrome21と同じような表示になりました。まぁベースがすべて同じなので当たり前といえばそうなのかもしれませんが。
ぜひ、Windowsのアプリケーションでも調べていただいて報告していただけると嬉しいです。