033.4 レッスン 1
Certificate: |
Web開発の要点 |
---|---|
Version: |
1.0 |
Topic: |
033 CSSコンテンツスタイリング |
Objective: |
033.4 CSSボックスのモデルとレイアウト |
Lesson: |
1 of 1 |
はじめに
HTML文書の中で目に見える各要素は、長方形のボックスとして表示されます。そのため、 ボックスモデル という言葉は、CSSが要素の視覚的なプロパティを変更する際のアプローチを表しています。異なるサイズの箱のように、HTML要素は コンテナ 要素(通常は div
要素)の中に入れ子にすることができ、セクションごとに分離することができます。
CSSを使ってボックスの位置を変更することができます。小さな調整から、ページ上の要素の配置を大幅に変更することまで可能です。各ボックスの位置は、通常フローに加えて、周囲の要素、親コンテナとの関係や、ユーザーに見えるページの領域である viewport との関係に基づいて決定することができます。1つの機構ですべてのレイアウト要件を満たすことはできないため、複数の機構を組み合わせて使用することになります。
通常フロー
ブラウザがドキュメントツリーをレンダリングするデフォルトの方法を 通常フロー と呼びます。要素に対応する四角形は、ドキュメントツリーに表示される順序とほぼ同じ順序で、親要素に対して配置されます。ただし、要素の種類によっては、対応するボックスの配置ルールが異なる場合があります。
通常フローのロジックを理解するには、ボックスを可視化するのがよいでしょう。まず、非常に基本的なページから始めましょう。3つの独立した div
要素があり、それぞれがランダムなテキストの段落を持っています。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CSS Box Model and Layout</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="first">
<h2>First div</h2>
<p><span>Sed</span> <span>eget</span> <span>velit</span>
<span>id</span> <span>ante</span> <span>tempus</span>
<span>porta</span> <span>pulvinar</span> <span>et</span>
<span>ex.</span></p>
</div><!-- #first -->
<div id="second">
<h2>Second div</h2>
<p><span>Fusce</span> <span>vitae</span> <span>vehicula</span>
<span>neque.</span> <span>Etiam</span> <span>maximus</span>
<span>vulputate</span> <span>neque</span> <span>eu</span>
<span>lobortis.</span> <span>Phasellus</span> <span>condimentum,</span>
<span>felis</span> <span>eget</span> <span>eleifend</span>
<span>aliquam,</span> <span>dui</span> <span>dolor</span>
<span>bibendum</span> <span>leo.</span></p>
</div><!-- #second -->
<div id="third">
<h2>Third div</h2>
<p><span>Pellentesque</span> <span>ornare</span> <span>ultricies</span>
<span>elementum.</span> <span>Morbi</span> <span>vulputate</span>
<span>pretium</span> <span>arcu,</span> <span>sed</span>
<span>faucibus.</span></p>
</div><!-- #third -->
</body>
</html>
すべての単語は span
要素の中にあるので、単語にスタイルを与えて、ボックスとしてどのように扱われるかを見ることができます。ボックスを表示するためには、HTMLドキュメントで参照されているスタイルシートファイル style.css
を編集する必要があります。以下のルールで必要なことができます。
* {
font-family: sans;
font-size: 14pt;
}
div {
border: 2px solid #00000044;
}
#first {
background-color: #c4a000ff;
}
#second {
background-color: #4e9a06ff;
}
#third {
background-color: #5c3566da;
}
h2 {
background-color: #ffffff66;
}
p {
background-color: #ffffff66;
}
span {
background-color: #ffffffaa;
}
結果は Figure 1 に表示されます。
Figure 1 では、各HTMLタグがレイアウト上で対応するボックスを持っていることを示しています。 div
、 h2
、 p
の各要素は、親要素の幅に合わせて拡張されます。例えば、 div
要素の親要素は body
要素なので、bodyの幅に合わせて拡張され、 h2
や p
要素の親要素は対応する div
です。親要素の幅に合わせて拡張されたボックスは、 block 要素と呼ばれます。ブロックとして表示される最も一般的なHTMLタグには、 h1
、 h2
、 h3
、 p
、 ul
、 ol
、 table
、 li
、 div
、 section
、 form
、 aside
などがあります。兄弟ブロック要素(同一の直系親要素を持つブロック要素)は、親要素の内側に上から下へと積み重ねられます。
Note
|
ブロック要素の中には、他のブロック要素のコンテナとして使用することを意図していないものがあります。例えば、 |
テキスト自体の他に、 h1
、 p
、 li
などの要素は、 inline 要素のみを子として想定しています。西洋の多くのスクリプトと同様に、インライン要素はテキストの左から右への流れに従います。右側に空きがなくなると、インライン要素の流れは、テキストと同じように次の行に続きます。インラインボックスとして扱われる一般的なHTMLタグには、 span
、 a
、 em
、 strong
、 img
、 input
、 label
などがあります。
サンプルのHTMLページでは、段落内のすべての単語が span
タグで囲まれており、対応するCSSルールで強調表示できるようになっています。図のように、各 span
要素は、左から右へと、親要素に空きがなくなるまで水平に配置されます。
要素の高さはその内容に依存するため、ブラウザはコンテナ要素の高さを調整して、そのネストしたブロック要素やインライン要素の行に対応させます。しかし、いくつかのCSSプロパティは、ボックスの形状、位置、およびその内部要素の配置に影響を与えます。
margin
と padding
のプロパティは、すべてのボックスタイプに影響します。これらのプロパティを明示的に設定しなくても、ブラウザは標準的な値を使っていくつかのプロパティを設定します。 Figure 1 に見られるように、 h2
と p
の要素は、それらの間にギャップがある状態でレンダリングされています。これらのギャップは、ブラウザがこれらの要素にデフォルトで追加する上下のマージンです。 h2
と p
のセレクタのCSSルールを変更することで、このギャップを取り除くことができます。
h2 {
background-color: #ffffff66;
margin: 0;
}
p {
background-color: #ffffff66;
margin: 0;
}
結果は Figure 2 に示されます。
margin
プロパティは、要素のマージンを変更または削除することができます。また、デフォルトでは、 body
要素には小さなマージンがあり、周囲にギャップが生じます。このギャップは、 margin
プロパティを使って取り除くこともできます。
要素の margin
プロパティが要素とその周囲との間のギャップを定義するのに対して、要素の padding
プロパティは、コンテナの限界とその子要素との間の内部ギャップを定義します。例えば、サンプルコードの各 div
の中にある h2
と p
という要素を考えてみましょう。これらの要素のmarginプロパティを使用して、対応する div
の境界にギャップを作ることもできますが、コンテナの padding
プロパティを変更する方が簡単です。
#second {
background-color: #4e9a06ff;
padding: 1em;
}
2つ目の div
のルールだけを変更したので、結果 (Figure 3) は2つ目の div
と他の div
コンテナの違いを表しています。
div
コンテナは、異なるパディングを持つことができます。margin
プロパティは、ボックスの4つの側面を制御する4つのプロパティの省略形です。 margin-top
、 margin-right
、 margin-bottom
、 margin-left
です。これまでの例のように、 margin
に1つの値が割り当てられている場合は、ボックスの4つの余白すべてが使用されます。2つの値が書かれている場合は、1つ目の値で上下の余白を、2つ目の値で左右の余白を定義します。例えば、 margin: 1em 2em
とすると、上下の余白は1em、左右の余白は2emと定義されます。4つの値を書くと、上から時計回りに4辺の余白が設定されます。短縮形プロパティの異なる値は、同じ単位を使用する必要はありません。
padding
プロパティも同様に、 margin
プロパティと同じ原則に従った短縮形です。
デフォルトの動作では、ブロック要素は利用可能な幅に合わせて伸縮します。しかし、これは必須ではありません。 width
プロパティでは、ボックスの水平方向のサイズを固定することができます。
#first {
background-color: #c4a000ff;
width: 6em;
}
CSSルールに width: 6em
を追加すると、最初の div
が水平方向に縮小され、その右側に空白ができます (Figure 4) 。
width
プロパティは、最初の div
の水平方向の幅を変更します。最初の div
を左寄せにするのではなく、中央寄せにしたい場合があります。ボックスを中央に配置することは、両側に同じ大きさのマージンを設定することと同じなので、marginプロパティを使って中央に配置することができます。利用可能なスペースの大きさが異なる場合があるので、左右のマージンには auto
の値を使用します。
#first {
background-color: #c4a000ff;
width: 6em;
margin: 0 auto;
}
左右の余白はブラウザで自動的に計算され、ボックスは中央に配置されます (Figure 5) 。
margin
プロパティは、最初の div
を中央に配置するために使用されます。このように、ブロック要素の幅を狭くしても、残りのスペースを次の要素に利用することはできません。あたかも幅の狭い要素がすべての幅を占めているかのように、自然な流れが維持されます。
通常フローのカスタマイズ
通常フローは、シンプルで連続的なものです。CSSでは、通常フローを断ち切って、特定の方法で要素を配置することができ、必要に応じてページのスクロールを上書きすることもできます。このセクションでは、要素の位置を制御するいくつかの方法を紹介します。
フローティング要素
兄弟のブロック要素が同じ水平方向のスペースを共有するようにすることは可能です。その方法の一つとして、 float
プロパティを使って、要素を通常フローから外すことができます。 float
プロパティは、その名の通り、ボックスを後続のブロック要素の上に浮かせて、あたかも浮いたボックスの下にあるかのようにレンダリングします。最初の div
を右にフロートさせるには、対応するCSSルールに float: right
を追加します。
#first {
background-color: #c4a000ff;
width: 6em;
float: right;
}
フロートされたボックスでは自動マージンは無視されるので、 margin
プロパティを削除することができます。 Figure 6 は、最初の div
を右にフローティングした結果です。
div
はフローティングで、通常フローには含まれていません。デフォルトでは、フローティング要素の後に来るすべてのブロック要素は、その下に入ります。したがって、十分な高さがあれば、フローティングボックスは残りのすべてのブロック要素を覆うことになります。
フローティング要素は、他のブロック要素よりも上に位置しますが、フローティング要素のコンテナ内のインラインコンテンツは、フローティング要素の周りに回り込みます。これは、雑誌や新聞のレイアウトでは、画像の周りにテキストを巻き付けることが多いことからヒントを得ています。
先ほどの画像では、1つ目の div
が2つ目の div
と3つ目の div
の一部をどのように覆っているかを示しています。ここで、1つ目の div
は2つ目の div
を覆うが、3つ目の div
は覆わないようにしたいとします。解決策は、3番目の div
に対応するCSSルールに clear
プロパティを含めることです。
#third {
background-color: #5c3566da;
clear: right;
}
clear
プロパティを right
に設定すると、対応する要素が右にフロートした前の要素をスキップし、通常フローに戻ります (Figure 7) 。
clear
プロパティは、通常フローに戻ります。同様に、前の要素が左に浮いていた場合には、 clear: left
を使用して通常フローに戻すことができます。左と右の両方に浮かんだ要素をスキップしなければならない場合は、 clear: both
を使用してください。
ポジショニングボックス
通常フローでは、各ボックスはドキュメントツリー内で前に来るボックスの後に進みます。前の兄弟要素は、後に続く要素を “押し” 、親要素の中で右や下に移動させます。親要素には、同じことを行う自分の兄弟が含まれる場合があります。これは、壁にタイルを上から順に並べていくようなものです。
このようにボックスを配置する方法を static(静的) と呼び、CSSの position
プロパティのデフォルト値となっています。マージンやパディングを定義する以外に、静的なボックスをページ内で再配置する方法はありません。
壁に貼られたタイルの例えのように、静的な配置は必須ではありません。タイルと同様に、ボックスを好きな場所に配置することができ、他のボックスを覆うこともできます。そのためには、 position
プロパティに以下のいずれかの値を割り当てます。
relative
-
要素はドキュメントの通常フローに従いますが、
top
、right
、bottom
、left
プロパティを使用して、元の静的な位置からのオフセットを設定することができます。オフセットは負の値にすることもできます。他の要素は、あたかも相対的な要素が静止しているかのように、元の位置に残ります。 absolute
-
この要素は、他の要素の通常フローを無視して、
top
、right
、bottom
、left
プロパティによって、ページ上の自分の位置を決めます。これらの値は、ドキュメントのボディまたは非静的な親コンテナに対する相対値です。 fixed
-
この要素は、他の要素の通常フローを無視して、
top
、right
、bottom
、left
プロパティによって、自身の位置を決めます。これらの値はビューポート(ドキュメントが表示される画面領域)に対する相対値です。固定要素は閲覧者がドキュメントをスクロールしても動くことはなく、画面上に固定されたステッカーのようなものです。 sticky
-
この要素は、ドキュメントの通常フローに従います。しかし、ドキュメントのスクロール時にビューポートの外に出るのではなく、
top
、right
、bottom
、left
の各プロパティで設定された位置で停止します。例えば、top
の値が10px
であれば、要素がビューポートの上限から10ピクセルに達した時点で、ビューポートの上部の下でスクロールを停止します。このとき、ページの他の部分はスクロールを続けますが、sticky要素はその位置で固定要素のように動作します。ドキュメントがスクロールしてビューポート内の元の位置に戻ると、元の位置に戻ります。スティッキー(sticky)要素は、最近では、常に表示されるトップメニューの作成によく使われています。
top
、 right
、 bottom
、 left
の各プロパティを使用できる位置は、すべてを使用する必要はありません。例えば、絶対要素の top
と height
プロパティの両方を設定した場合、ブラウザは暗黙のうちに bottom
プロパティを計算します(top + height = bottom)。
display
プロパティ
通常フローによる順序はデザイン上問題にならないが、ボックスのページ内での配置を変更したい場合は、要素の display
プロパティを変更します。 display
プロパティは、 display: none
を設定することで、レンダリングされたドキュメントから要素を完全に消失させることもできます。これは、JavaScriptを使って後で要素を表示したいときに便利です。
display
プロパティは、例えば、ブロック要素をインライン要素のように振る舞うことができます( display: inline
)。しかし、このような方法は良い習慣とは言えません。コンテナ要素を並べて配置するには、 フレックスボックス モデル のようなより良い方法があります。
フレックスボックス モデルは、フロートの限界を克服し、ページレイアウトを構成するテーブルの不適切な使用をなくすために考案されました。コンテナ要素の display
プロパティを flex
に設定してフレックスコンテナにすると、その直系の子供たちは多かれ少なかれテーブルの行のセルのように動作します。
Tip
|
ページ上の要素の配置をさらにコントロールしたい場合は、 CSSグリッド 機能を見てみましょう。グリッドは、行と列をベースにした強力なシステムで、凝ったレイアウトを作ることができます。 |
フレックス表示をテストするために、サンプルページに新しい div
要素を追加し、それを既存の3つの div
要素のコンテナにします。
<div id="container">
<div id="first">
<h2>First div</h2>
<p><span>Sed</span> <span>eget</span> <span>velit</span>
<span>id</span> <span>ante</span> <span>tempus</span>
<span>porta</span> <span>pulvinar</span> <span>et</span>
<span>ex.</span></p>
</div><!-- #first -->
<div id="second">
<h2>Second div</h2>
<p><span>Fusce</span> <span>vitae</span> <span>vehicula</span>
<span>neque.</span> <span>Etiam</span> <span>maximus</span>
<span>vulputate</span> <span>neque</span> <span>eu</span>
<span>lobortis.</span> <span>Phasellus</span> <span>condimentum,</span>
<span>felis</span> <span>eget</span> <span>eleifend</span>
<span>aliquam,</span> <span>dui</span> <span>dolor</span>
<span>bibendum</span> <span>leo.</span></p>
</div><!-- #second -->
<div id="third">
<h2>Third div</h2>
<p><span>Pellentesque</span> <span>ornare</span> <span>ultricies</span>
<span>elementum.</span> <span>Morbi</span> <span>vulputate</span>
<span>pretium</span> <span>arcu,</span> <span>sed</span>
<span>faucibus.</span></p>
</div><!-- #third -->
</div><!-- #container -->
スタイルシートに以下のCSSルールを追加して、コンテナ div
をフレックスボックスコンテナにします。
#container {
display: flex;
}
その結果、3つの内側の div
要素が並んでレンダリングされます (Figure 8) 。
flex
ではなく inline-flex
という値を使うと、基本的には同じ結果になりますが、子要素の挙動がインライン要素に近くなります。
レスポンシブデザイン
CSSには、画面の大きさに合わせて要素やフォントのサイズを調整するプロパティが用意されています。しかし、さらに進んで、デスクトップと一定の大きさ以下の画面サイズのデバイスでは、異なるデザインを使用したいと思うこともあるでしょう。これを レスポンシブWebデザイン と呼びますが、CSSではこれを実現するために メディアクエリ と呼ばれる手法が用意されています。
先ほどの例では、 div
要素を列に並べて配置するようにページレイアウトを変更しました。このレイアウトは大きな画面には適していますが、小さな画面ではごちゃごちゃしすぎてしまいます。この問題を解決するには、スタイルシートにメディアクエリを追加して、幅が最低でも 600px
のスクリーンのみにマッチさせます。
@media (min-width: 600px){
#container {
display: flex;
}
}
@media
ディレクティブ内のCSSルールは、カッコ内の基準が満たされた場合にのみ使用されます。この例では、ビューポートの幅が 600px
未満の場合、コンテナの div
にはルールが適用されず、その子は従来の div
要素としてレンダリングされます。ブラウザはビューポートの寸法が変わるたびにメディアクエリを再評価するので、ブラウザのウィンドウサイズを変更したり、スマートフォンを回転させたりしながら、リアルタイムにレイアウトを変更することができます。
演習
-
もし
position
プロパティが変更されない場合、ブラウザはどのような位置合わせ方法を使用しますか? -
要素のボックスが、それまでフローティングされていた要素の後にレンダリングされることをどのように確認できますか?
-
margin
短縮形プロパティを使って、上下のマージンを4px
に、左右のマージンを6em
に設定するにはどうしたらいいですか? -
固定幅の静的コンテナ要素を、ページ上で水平方向にセンタリングするにはどうすれば良いでしょうか?
発展演習
-
要素 '<div class="picture">` に合わせて、それに続くブロック要素内のテキストが右端に寄っていくようなCSSルールを書いてください。
-
top
プロパティは、親要素と比較して静的要素にどのように影響しますか? -
要素の
display
プロパティをflex
に変更すると、通常フローでの配置はどうなりますか? -
画面の大きさに応じてルールを使い分けることができるCSSの機能は何でしょうか?
まとめ
このレッスンでは、CSSのボックスモデルと、それをカスタマイズする方法について説明しました。ドキュメントの通常フローに加えて、デザイナーはさまざまな位置関係のメカニズムを利用して、カスタムレイアウトを実装することができます。このレッスンでは、以下の概念と手順を説明しました。
-
ドキュメントの通常フロー
-
要素のボックスのmarginとpaddingの調整
-
floatおよびclearプロパティの使用
-
位置決めの仕組み(position):静的(static)、相対(relative)、絶対(absolute)、固定(fixed)、スティッキー(sticky)
-
display
プロパティの代替値 -
レスポンシブデザインの基本
演習の回答
-
もし
position
プロパティが変更されない場合、ブラウザはどのような位置合わせ方法を使用しますか?static
-
要素のボックスが、それまでフローティングされていた要素の後にレンダリングされることをどのように確認できますか?
要素の
clear
プロパティをboth
に設定します。 -
margin
短縮形プロパティを使って、上下のマージンを4px
に、左右のマージンを6em
に設定するにはどうしたらいいですか?margin: 4px 6em
またはmargin: 4px 6em 4px 6em
です。 -
固定幅の静的コンテナ要素を、ページ上で水平方向にセンタリングするにはどうすれば良いでしょうか?
margin-left
とmargin-right
のプロパティにauto
の値を使用します。
発展演習の回答
-
要素
<div class="picture">
に合わせて、それに続くブロック要素内のテキストが右端に寄っていくようなCSSルールを書いてください。.picture { float: left; }
-
top
プロパティは、親要素と比較して静的要素にどのように影響しますか?top
プロパティは、静的な要素には適用されません。 -
要素の
display
プロパティをflex
に変更すると、通常フローでの配置はどうなりますか?要素自体の配置は変わりませんが、直下の子要素が水平方向に並んでレンダリングされます。
-
画面の大きさに応じてルールを使い分けることができるCSSの機能は何でしょうか?
メディアクエリ により、CSSルールを適用する前に、ブラウザがビューポートの寸法を確認することができます。