はじめに
今回解決したいのはこれです。
「overflow-wrap
かけたのに改行されないしテーブルwidthもなんか勝手に伸ばされちゃってる問題」です。
こんなんHTML / CSSの初歩中の初歩じゃんwwwという方は、どうぞごゆるりとブラウザバックしてやってくださいませ…
「それ地味に悩んでた!」という方がもしいらっしゃいましたら、少しでも助けになれれば嬉しいです。というか一緒に悩みましょう。
あ、でも、もしそんな方が本当にいたら、こんなことに悩むよりも、
「全半角記号のブラウザテストだけ許容する」という呪文を唱えた方が5億倍早いです…というネタバレだけ先にしておきますね><
もくじ
当記事は、以下の内容に関するメモ書きです。
- CSSの改行処理プロパティのメリデメ
- 上記問題の暫定解決方法
対象のCSSプロパティは以下の通りです。
overflow-wrap: break-word;
word-wrap: break-word;
word-break: break-all;
word-break: break-word;
環境
記事のスクショは、下記環境で作成しています1。
OS | ブラウザ |
---|---|
MacOS 10.15 | Chrome |
overflow-wrap: break-word;
こんな時にオススメ!:
「コンテナからなるべくはみ出したくはないけど…禁則処理2もなるべく入れたいし…英単語も可能な限り綺麗な状態で表示させたいなぁ〜!」という時。
メリット:
- ブラウザ:Chrome, Edge, IE, FireFoxなど、主要ブラウザで対応
- 禁則処理:可能な限り保たれる
- コンテナ(テキストの表示領域)幅より長い英単語:強制的に折り返される
- 記号の連続の折り返し:対応
デメリット:
- テーブル内のセルでは適用されない…………(※詳細下記)
処理の詳細は、MDNのCSSリファレンスで以下のように定義されています。
インライン要素に対して、テキストが行ボックスをあふれないように、ブラウザーが不可分の文字列の途中で改行を入れるかどうかの設定を適用します。
下記サイトの説明がより分かりやすいです。
単語の途中で折り返さないと行ボックスの幅からあふれてしまうときのみ、その単語の途中で折り返します。単語の途中で折り返しが発生するのは、その単語の幅が行ボックスの幅より大きい場合のみとなります。つまり、可能な限り禁則処理が保持され、可能な限り単語途中での折り返しを避けることができます。
https://w3g.jp/blog/confusing_word-break_word-wrap より
overflow-wrap: break-word;
は、「単語内改行をしないこと」より「コンテナ幅」を優先する設定です。次に入力される単語がコンテナ幅の残りを超えそうな場合、単語内で改行しないように単語ごと次の行に送る制御をします。
上記の処理だけでは対応できない場合、例えば1語の長さがコンテナ幅を超えてしまう場合は、単語の途中で折り返すことを許容して、コンテナ幅に収めるという設定です。
たとえば、世界一長い地名Tetaumatawhakatangihangakoauaotamateaurehaeaturipukapihimaungahoronukupokaiwhenuaakitanarahu
が入力されてコンテナを超えてしまうような場合、単語途中での折り返しが発生します。
逆に、「コンテナ幅」より「単語内改行をしないこと」を優先させたい場合は、overflow-wrap: normal;
を設定します(デフォルトの値なので設定しなくても大丈夫です)。
Tetaumatawhakatangihangakoauaotamateaurehaeaturipukapihimaungahoronukupokaiwhenuaakitanarahu
が入力された場合には、コンテナ幅をはみ出すことを許容して、単語内の改行を防ぐ結果になります。
※ただし、overflow-wrap(word-wrap)
プロパティはテーブル内のセルには使用できません。
詳しく言うと、overflow-wrap(word-wrap)
プロパティはテキストの長さとコンテナ幅を計算して折り返し可否を決めていますが、テーブルのデフォルトCSS設定である自動レイアウトアルゴリズムtable-layout:auto;
も、中身のテキストによってレイアウトを計算するプロパティです。
このため、重ね掛けするとoverflow-wrap(word-wrap)
側の計算がうまく効かなくなってしまうようなのです。
word-wrap: break-word;
word-wrap
プロパティはoverflow-wrap
プロパティの前身です。
CSS3の仕様書では現在、後方互換性のためにoverflow-wrap
プロパティを使用する実装者は対応するword-wrap
プロパティも併記することを推奨しています。
いやテーブルで改行したいねんな!!!!
overflow-wrap
やword-wrap
は正直すごい。天才。
日本語も英語も記号も良きところで良き感じに改行してくれる。もうこれがベストプラクティス。
いや普通の実装だったらほんとoverflow-wrap
先生に任せて、副担にword-wrap
おじいちゃんをつけておいてあげればまず間違いない。分かってる。
でもこれで満足する人間だったらQiita書いてないんだな。
今回の課題はこれです(再掲)。
「そんな天才的なoverflow-wrap
先生をかけたのに改行されないし、テーブルwidthもなんか勝手に伸ばされちゃってる問題」です。
自動計算アルゴリズムかなんか知らんが、やってくれやがりましたな…
大体のフォームやアンケートや個人情報ページなどには、文字数確定部分だけじゃなくて自由記述欄もあったりするかと思うのですが、
生半可にテキスト文字数可変項目を含むテーブルを作ると、自由記述欄に!マークが100文字とか入ったらレイアウトが死ぬ可能性が発生しちゃう…
次に紹介するのは、そんな逆境で出会った、悪魔のようなプロパティです。
どうぞ。
word-break: break-all;
こんな時にオススメ!:
「**死んでも絶対レイアウト崩したくねえ〜〜〜〜!!!!!!**行頭の句読点とか気にしないし、英語とかマジぶつ切りになってもいいから、とにかく絶対にコンテナからはみ出させねえ(強い意志)」という時。
メリット:
- ブラウザ:Chrome, Edge, IE, FireFoxなど、主要ブラウザで対応
- コンテナ幅より長い英単語:強制的に折り返される
デメリット:
- 禁則処理:ほとんど解除されてしまう
- コンテナ幅より短い英単語で、単語全体を次の行に送れば途中で改行を防ぐことができる場合であっても、テキストがコンテナから溢れたところで強制的に折り返してしまう
- 一部記号(!や?など)の連続に対応していない……
MDNのCSSリファレンスでは以下のように定義されています。
単語中などでの文字の改行に関する禁則処理を解除し、どの文字の間でも改行するようにします。
みんな大好きword-break: break-all;
。何があっても強制改行してくれます。心強い。
英単語が入るとめちゃめちゃ読みづらいのですが、正直日本語は単語の区切れ目でなくても改行できる言語なので、そんなに気にしなくても…(悪魔のささやき)
overflow-wrap
やword-wrap
の細かいプロパティでこちゃこちゃ悩みたくねえ!!とにかく「単語内改行をしないこと」より「コンテナ幅」を最優先したい!という場合は、結局これを選んでしまうのです…(悪魔のささやき)
しかし禁則処理の(ほぼ)全解除なので、日本語でも句読点が行頭に来るなど、若干気になる人は気になる処理になってしまいます。
ちなみに、overflow-wrap(word-wrap): break-word;
とword-break: break-all;
を重ね掛けした場合は、word-break: break-all;
が優先されてしまうそうです。圧倒的パワー。
何があっても強制改行と言ったな?あれは嘘だ
さて、禁則処理や英語をかなぐり捨てて「「「力」」」を手に入れた我々なので、きっと理想のテーブルが出来上がったことでしょう!!!!
そうですね、無情ですね。
詳しい理由は分かりませんが、CSS3の仕様書でも、word-break: break-all;
は以下のように説明されています。
Breaking is allowed within “words”
(「語句」内での改行を行う)
stackoverflowでも「記号$がword-break: break-all;
で改行されない」という質問に対して、以下のような回答がついています。
ユニコードで「文字」「数字」ではなく「記号」として分類されているものは、禁則処理が弱いのでは
word-break: break-all;
でも、テーブル内で一部記号の連続を改行することは難しいのかな…
としょげたその時、
天使が現れました。
word-break: break-word;
こんな時にオススメ!:
「IEとEdgeは捨てた。改行させてくれ」
メリット:
- 禁則処理:可能な限り保たれる!
- コンテナ(テキストの表示領域)幅より長い英単語:強制的に折り返される!!
- 記号の連続の折り返し:対応!!!
- テーブル内のセルにかけてもちゃんと効く!!!!
デメリット:
- ブラウザ:IEとEdgeには非対応
公式では以下のように定義されています。
行内で適切に改行できる場所が他にない場合に限って、単語の途中でも改行するようにします。
(https://developer.mozilla.org/ja/docs/Web/CSS/word-breakより)
いやこれがマジでやりたかった(なおIEとEdgeは非対応)。
これがマジでやりたかったんだが、word-break
プロパティの中でもなぜかこれだけIEとEdge非対応なんだな…………
IEとEdgeのことだけ都合よく記憶喪失になった人にだけ使用が許される、天使のように天真爛漫純粋無垢かつ無情なプロパティ。
暫定解決方法
このようにいろいろ試行錯誤しまして、以下条件での暫定の解決方法を見つけました。
- 主要ブラウザ(Chrome, FireFox, IE, Edge)対応
- 英語や句読点にはなるべく禁則処理を入れたい
- コンテナ幅を超える英単語だけは単語の途中で折り曲げても良い
- 記号の連続も折り返したい
- とにかく枠を広げたくない
無理やろ…と思いましたが、案外いけたんですよね。
tdの中にdivを作成し、クラス属性に以下を設定する
- width
overflow-wrap: break-word;
これだけでした。なんて簡単なんだ…divだったのか…
tdにwidth, overflow-wrap: break-word;
を直接指定してもうまくいかなかったです。table-layout: auto;
のせいですかね…
おわりに
試行錯誤してやっと見つけたわりにはしょぼい解決法ですし、テーブル設計的に一部のtdだけ中にdiv入れるのってどうなの?とも思うのですが、自分はちょっとこれで力尽きました。。
HTML / CSSに詳しい人にぜひイケてるHTML設計アドバイス欲しいです…
「暫定解決方法でも、まあ、ウン…大丈夫だよ!動くよ!(生暖かい目)」ということであれば、そっといいねしていただけると嬉しいです😂
お読みいただきありがとうございました!
暫定解決方法②(2020/01/29追記)
「table-layout: auto;
をtable-layout: fixed;
に変更する」
今回やりたいこと自体はoverflow-wrap: break-word
の章でちらっと触れたtable-layoutプロパティを
auto(デフォルト)→fixedに変更することで、td配下にdivの入れ子を作らなくても実現可能です!むしろこっちの方が簡単でした!
(コメント欄で検証いただいています。@yshimizu125 さん、ありがとうございます!)
ただし、デメリットとして
「既存サイトのtableのCSSを変えると、影響範囲が大きくなってしまう」
という理由があり、自分は使用できなかったのですが、
新規のHTMLページを作る予定で、table-layout: auto;
にする必要がない人は、初めからtable-layout: fixed;
をtableのCSSとして設定しておくと良いかもしれません!
-
暫定解決方法については、Windows 10やIE, Edge, FireFoxでも試行しましたが、間違い等ありましたら申し訳ありません。 ↩
-
句読点、とじかっこなどの記号が行頭に来ないようにするルール。https://ja.wikipedia.org/wiki/%E7%A6%81%E5%89%87%E5%87%A6%E7%90%86 ↩