はじめに
今回はCSSの基礎の復習とキャッチアップを中心とした記事です。
近年のWeb開発では、フロントエンドとバックエンドは明確に分離されつつも、どちらも区別せずに同じチームで取り組むことも増えてきました。
プロダクトエンジニアとも呼ばれたりしますが、単純な技術だけでなく、UI/UXのデザインやドメインの知識までプロダクトに関連することはすべて解決する姿勢が求められます。
個人的にもWEBエンジニアになりたてのころはバックエンドの業務が中心でしたが、だんだんとフロントエンドの領域に手を伸ばしつつあります。
SPAの普及やNode.jsをはじめとするサーバーサイドでのJavaScriptの利用が増えたこともあり、フロントエンドの技術はますます重要になってきています。
業務においては課題解決を優先するためにモダンなフレームワークを触れることがどうしても多くなりますが、体系的にCSSを学ぶ機会がこれまでなかったので、改めて基礎から学び直すことにしました。
また、近年はアプリケーションやWebサイトの品質において、アクセシビリティが非常に重要視されるようになってきました。
特に公共性の高いサイトや商用のサイトでは、障害のある方や高齢者も含め、全てのユーザーが快適に使えるデザインが要求されます。
アクセシビリティに関するMDN内の説明は以下の通りです。
アクセシビリティというのはあなたのウェブサイトを可能な限り多くの人に利用してもらうようにすることです。かつては我々はアクセシビリティのことをハンディキャップを持つ人々のためのものだと考えていましたが、現在はモバイル端末や遅いネットワークを利用している人々のためのものでもあると考えられています。
CSSの基本
今回はバックエンド中心のエンジニアから見る再入門用の記事のため、基本的な部分は省略します。 本当に基本的な部分はMDNのドキュメントなどを参照してください。
ボックスモデル
CSSにおいて、要素はボックスとして扱われます。
これを「ボックスモデル」と呼び、具体的には以下の4つの領域から構築されます。
- コンテンツ領域(content box)
要素内のテキストや画像、子要素など、実際に表示されるコンテンツが配置される部分です。width
やheight
などのプロパティを使用して制御し、指定しない場合はコンテンツの量に応じてこの領域の大きさが決まります。 - パディング領域(padding box)
コンテンツ領域の外側にある余白領域です。padding
プロパティおよび関連するプロパティを使用して制御します。背景色や背景画像が設定されている場合、コンテンツ領域だけでなくパディング領域にも適用されます。 - ボーダー領域(border box)
要素の枠線を示す部分で、太さや色、スタイル(実線や点線など)を指定できます。 - マージン領域(margin box)
要素の外側にある余白で、隣接する要素との距離を決める役割を担います。マージンは背景色の影響を受けず、通常は透明(要素の背景色が適用されない)です。 コンテンツ、パディング、およびボーダーを囲うかたちになります。
コンテンツボックスとボックスサイズの計算
ボックスモデルには、標準ボックスモデルと代替ボックスモデルがあります。
既定では、ブラウザーは標準ボックスモデルを使用します。
- content-box(標準ボックスモデル)
デフォルトの状態では、ボックスサイズは「コンテンツ領域」の幅と高さがwidthとheightプロパティで指定され、その外側に指定したパディングやボーダーが加算されます。これを「標準ボックスモデル」と呼びます。
例えば、以下のようなコードを考えます。
.box {
width: 200px;
height: 100px;
padding: 10px;
border: 2px solid #000;
margin: 20px;
}
この要素の、見た目上の横幅は、以下のように計算されます。
- コンテンツ領域の幅: 200px
- パディング: 左右それぞれ10pxずつ
- ボーダー: 左右それぞれ2pxずつ
- 合計: 200px + 10px + 2px + 10px + 2px = 224px
同様に、高さ方向でもパディングやボーダーが足し算され、最終的な要素の高さが決まります。
標準ボックスモデルでは、widthとheightプロパティで指定した値がコンテンツ領域のサイズとなり、その外側にパディングやボーダーが追加されます。
- border-box(代替ボックスモデル)
一方、box-sizing
プロパティをborder-box
に設定することで、ボックスサイズの計算方法を変更できます。
代替ボックスモデルを使用すると、幅はページ上に表示されるボックスの幅になります。
コンテンツ領域の幅は、その幅からパディングとボーダーの幅を引いた値になります。
.box-border-box {
box-sizing: border-box;
width: 200px;
height: 100px;
padding: 10px;
border: 2px solid #000;
}
この例だと、ボックス領域が占める幅は200pxになります。
つまり、標準ボックスモデルよりも最終的なサイズを調整しやすくなるメリットがあります。
このような直感的なサイズ指定ができることや、異なるブラウザ間でのレンダリングの差異を吸収するために、代替ボックスモデルを使用するケースが増えています。
パディング、ボーダー、マージンの詳細
パディング
パディングは、コンテンツとボーダーの間にある余白です。
背景色や背景画像はパディング領域にも適用されます。
マージンとは異なり、負のパディングを指定することはできません。
padding
プロパティは、要素のすべての辺のパディングを制御し、各辺を個別に制御するには、以下の個別指定プロパティを使用します。
padding-top
padding-right
padding-bottom
padding-left
ボーダー
ボーダーは、要素を囲む枠線のスタイルです。
標準ボックスモデルの場合はボーダーのサイズがコンテンツボックスのwidthとheightに追加されます。
代替ボックスモデルを使用している場合、境界のサイズが利用可能なwidthとheightの一部を占めるため、コンテンツボックスが小さくなります。
パディングと同様に4つの辺を個別に指定するプロパティが用意されています。
border-top
border-right
border-bottom
border-left
また、すべての辺の幅、スタイル、色を設定するためのスタイルは下記です。
border-width
border-style
border-color
これらは省略形として、
border: 2px solid #000;
のように一括指定することもできます。
単一の辺の幅、スタイル、色を書斎に設定する場合には個別指定プロパティも用意されています。
border-top-width
border-top-style
border-top-color
border-right-width
border-right-style
border-right-color
border-bottom-width
border-bottom-style
border-bottom-color
border-left-width
border-left-style
border-left-color
インライン要素とブロック要素のボックスモデル
要素にはブロック要素とインライン要素があります。これまで紹介したボックスモデルは、主にブロック要素に適用されますが、プロパティのいくつかはインライン要素にも適用されます。
ブロック要素は横幅が可能な限りいっぱいに広がり、上下に改行を伴います。
インライン要素はテキストの流れの中に配置され、基本的には横幅や高さを直接指定できません。
また、上下方向のmargin
やpadding
はテキスト行の高さやレイアウトに大きく影響しない場合があります。
- ブロック要素の例
<div>
<p>
<h1>
〜<h6>
<ol>
<ul>
<li>
- インライン要素の例
<span>
<a>
<strong>
<em>
<img>
CSSのdisplay
プロパティを使用して、ブロック要素をインライン要素に変更することもできます。
display: inline-block
の利用
display: inline-block
は、インライン要素とブロック要素の両方の特性を持つ表示形式です
- インラインフロー
- インライン要素のように、周囲のテキストや他のインライン要素と同じ行に並び、改行されません。
- ブロック要素の特性
- ブロック要素のように、
width
やheight
、margin
、padding
、border
プロパティを使用して要素を制御できます。
- ブロック要素のように、
利用例:
- 横並びのレイアウト
- 複数の要素を同じ行に配置しつつ、各要素に対して独自の幅や高さを設定したい場合。例えば、ナビゲーションメニューの各項目など。
ボックスモデルの典型的な問題と対処
ボックスモデルの幅の計算
繰り返しになりますが、標準ボックスモデルでは、width
プロパティで指定した値はコンテンツ領域の幅になり、その外側にパディングやボーダーが追加されます。そのため、width
を指定し、さらにパディングやボーダーを追加すると、思っていたよりも要素が大きくなることがあります。
このようなケースはあらかじめパディングやボーダーを考慮したサイズを指定するか、代替ボックスモデルを使用することで解決できます。
マージンの折り重なり(collapsing margins)
隣接するブロック要素の上下マージンは、重複して大きなマージンにならないように、実際は一方の大きい値のみが 適用される「マージンの相殺」と呼ばれる現象がおきます。
これは仕様ではあるものの、直感的な挙動ではないため、指定したmarginが効いていないのでは、と誤解されやすいです。
回避する方法としては余白を入れる方向を統一したり、要素にborderやpaddingを設定するといった方法があります。
そもそも親要素にdisplay: flex
やdisplay: grid
を指定することで、マージンの折り重なりを回避することもできます。
まとめ
今回はCSSの基礎の復習とボックスモデルについて学びました。
CSSのアップデートや細かい仕様などは、困った時にドキュメントを参照することはありますが、体系的に学ぶことができていなかったので、改めて基礎から学び直すことができました。
今後、バックエンドとフロントエンドの境界は曖昧になっていくことを踏まえても、エンジニアとしてはどちらも理解しておくことが重要だと感じました。