(編集部にて一部加筆修正しております。最終更新:2024年6月5日)
現在、CSSによる画面開発はレスポンシブデザインであることが当たり前となってきております。
Bootstrap・Semantic UI・BulmaなどのCSSフレームワークの充実により、高度なレスポンシブ対応CSSを簡単に生成することができ、AutoprefixerやLinterを含んだ開発環境を構築することで、マークアップ作業時にベンダー個別による不具合やタイプミスによる不具合は考えなくて良いほど少なくなっています。
それでも人が手でCSSをカスタマイズする場合は、表示崩れ、不具合との戦いになります。
しかし、それらの不具合はパターンがバラバラであるように見えて、実は根本的な原因がほぼ同じである可能性が高いです。
この根本的な原因に焦点を当て、特に開発現場で多く発生している原因を3つに絞って解説した上で対策方法を探っていきましょう。
表示崩れの根本的な原因を発生頻度でまとめるとほぼ以下のようになります。
- コンテンツ・モデルの理解不足 (全体の40%程度)
- 高さの固定 (全体の20%程度)
- marginの過度な使用 (全体の10%程度)
目次
1. コンテンツ・モデルの理解不足
CSS以前の問題として、HTMLが正しく書かれていなければ表示崩れにつながります。
黎明期のHTMLには「ブロックレベル要素」と「インライン要素」が存在し、「インライン要素」については、以下のコンテンツ・モデルの指向のもと開発されています。
- インライン要素はデータや他のインライン要素のみを含む。
- ブロックレベル要素をインライン要素の中に置くことはできない。
つまり、上記の指向に反する形でHTMLが作成されている場合、高確率で表示崩れ、不具合が発生します。
HTML5ではコンテンツ・モデルが大幅に見直されましたが、要点は同じです。「インライン要素」という名前が廃止され、段落などの中に含まれる文節・語句などを表す「フレージング・コンテンツ」として定義しなおされました。HTML5のコンテンツ・モデルでは、フレージング・コンテンツは必ず最終の子要素となるように定義されています。
そして、フレージング・コンテンツは文節・語句のみを含むため、CSSについても文節・語句にのみ反映させることができるプロパティ(color, size, weight等)を設定するべきだと想定できます。
これに反したCSSを設定した場合についても、高確率で表示崩れ、不具合が発生します。
【対策方法】
- HTML5のコンテンツ・モデルを正しく理解する。
- フレージング・コンテンツに設定できるCSSプロパティを正しく理解する。
2. 高さの固定
Webページのマークアップを行うときに最も重要となるのはデザイン原案であり、そのデザインを再現するためにCSSのカスタマイズを行っていくわけですが、Sketch・InVision・Figma などのピクセル単位でデザイン設計できるツールを参考にマークアップする際に起こる事が多いのがこの「高さの固定」です。
これらのデザインツールでは、ボタンなどのパーツの幅・高さが固定値(ピクセル)で定義されます。そのため、定義された幅・高さでパーツのCSSを作成すれば、数値上は問題なしということになってしまい、これが高さが固定される主な要因となっています。
レスポンシブデザインにおいて、要素の高さを固定するということは「レスポンシブの否定」を意味します。
画面幅が狭くなったとき、要素を縦に伸ばせなくなり表示崩れ、不具合が発生します。
逆に、要素の高さの固定が許される場面は以下の2点に限られる認識です。
- 内部で縦スクロール可能な要素を作成する場合。
- アイコンなど、完全にサイズが決まっている要素を作成する場合。
【対策方法】
- レスポンシブ部品にはheightプロパティは使用しない。
- 縦方向のサイズはpadding, margin等の余白プロパティを使って再現する。
3. marginの過度な使用
余白にmarginを多用するのはまったくもっておすすめではありません。なぜなら「marginの相殺」が存在するからです。
marginの相殺とは主に、隣接兄弟要素間で接しているmarginが、大きいサイズの方のmarginに結合される動作のことを指します。例えば、上の要素のmargin-bottomが10px、下の要素のmargin-topが20pxだとします。この場合、30pxとはならず、大きい方のmarginだけが残り、20pxだけが適用されるのです。この他に「親と子孫を隔てる要素」がない場合や「空要素」の場合も結合される場合があり、これらのケースが組み合わさると、原因を追うのを思わず躊躇してしまうようなスパゲティ状態の表示崩れにつながってしまう可能性があります。
そのため要素に余白を設定する場合、padding, marginどちらにするか深く考慮する必要があります。
「marginの相殺」を起こさず、かつコンポーネント化がしやすい余白設定を目指すにはルールが必要です。「marginの相殺」を起こさない一番の方法は要素間のmarginを隣接させないことです。上述した通り、要素の上下にmarginを設定すると縦並びのとき接してしまうので「margin-bottomだけを設定し、margin-topは設定してはいけない」といったルールを決めることで回避ができます。
このようなルールの提案として対策方法をまとめてみました。
【対策方法】
- margin-bottomだけを設定し、margin-topのみ設定する。(上述の通り)
- なるべく親子間の余白はpaddingで設定する。(親子間の余白をpaddingとすることで、子要素の外部marginの設定が必要なくなるので、パーツとしての再利用が可能となる)
最後に
これら3点を常に考慮することによって表示崩れの根本原因の大半をカバーすることができ、工数の削減に貢献できるはずです。
CSSのカスタマイズにおいては「正しく、単純明快に」を心がけて開発していきたいです。