メインコンテンツまでスキップ

CSSによるレイアウト

この節では、CSSを使用してHTML要素のレイアウトを調整する方法を学びます。

例として、次のような料金プランを表すカードを作ることを目標に進めていきます。

料金プランのカードの完成形

まずは、HTMLとCSSで料金プランのカードを作り始めてみます。

index.html
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>料金プラン</title>
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<div id="container">
<div class="card">
<div class="plan">Free</div>
<div class="price">無料</div>
<button type="button" class="button">今すぐ始める</button>
<ul>
<li>基本的な機能</li>
</ul>
</div>
<div class="card">
<div class="plan">Basic</div>
<div class="price">$5</div>
<button type="button" class="button">今すぐ始める</button>
<ul>
<li>基本的な機能</li>
<li>AIアシスタントのサポート</li>
<li>5GBのストレージ</li>
</ul>
</div>
<div class="card">
<div class="plan">Premium</div>
<div class="price">$20</div>
<button type="button" class="button">今すぐ始める</button>
<ul>
<li>全ての機能</li>
<li>AIアシスタントのサポート</li>
<li>20GBのストレージ</li>
</ul>
</div>
</div>
</body>
</html>
style.css
body {
background-color: #f0f0f0;
}

.card {
background-color: #fff;
}

.plan {
font-weight: bold; /* 太字にする */
font-size: 24px;
}

.price {
font-size: 20px;
}

.button {
background-color: #0d6efd;
color: #fff;
font-size: 16px;
}
16進数カラーコード

#f0f0f0#0d6efdのように、6桁の英数字で色を指定する記法を16進数カラーコードと呼びます。左から順に2桁ずつが、それぞれ赤・緑・青の成分を16進数で表しています。

また、省略形として3桁で指定することもできます。例えば、#1da#11ddaaと同じ意味になります。

幅と高さ

今のところ、カードの幅が画面いっぱいに広がってしまっています。

widthプロパティを指定する前のカード

widthプロパティで要素の幅を設定することができます。カードに適切な幅を設定するには、次のようにします。

.card {
background-color: #fff;
width: 240px;
}

widthプロパティを指定したカード

なお、widthプロパティで幅を設定したのと同様に、高さを設定したい場合はheightプロパティを使うことができます。

widthプロパティやheightプロパティの値には、親要素などに占める割合を表すパーセント値を指定することもできます。ボタンの幅がその親要素であるカードいっぱいに広がるようにするには、次のようにします。

.button {
background-color: #0d6efd;
color: #fff;
font-size: 16px;
width: 100%;
}

ボタンのwidthプロパティに100%を指定したカード

ブロック要素とインライン要素

HTML要素は、それらが表示される際のデフォルトの振る舞いにおいて分類することができます。

divh1pなどの要素は一般にブロック要素と呼ばれます。これらは新しい行から始まり、widthプロパティやheightプロパティが設定できます。widthプロパティを設定しない場合は親要素いっぱいに広がります。

spanastrongなどの要素は一般にインライン要素と呼ばれます。これらは新しい行から始まらず、widthプロパティやheightプロパティも設定できず、内容に応じた幅・高さになります。

ボーダー

borderプロパティを使って、ボーダーと呼ばれる境界線を設定することができます。次の例では、カードにボーダーを追加しています。

.card {
background-color: #fff;
width: 240px;
border: 1px solid #bbb;
}

borderプロパティに3つの値を指定する場合、それらの値はボーダーの幅・種類・色を表します。

また、borderプロパティにnoneを指定するとボーダーは表示されなくなります。次の例では、ボタンに付いていたデフォルトのボーダーを消しています。

.button {
background-color: #0d6efd;
color: #fff;
font-size: 16px;
width: 100%;
border: none;
}

borderプロパティを設定したカード

border-radiusプロパティで角を丸めることができます。指定する値は半径の大きさです。次の例では、カードの角とボタンの角を丸くしています。

.card {
background-color: #fff;
width: 240px;
border: 1px solid #bbb;
border-radius: 8px;
}
.button {
background-color: #0d6efd;
color: #fff;
font-size: 16px;
width: 100%;
border: none;
border-radius: 8px;
}

border-radiusプロパティを設定したカード

マージン

marginプロパティを使って、マージンと呼ばれる余白を設定することができます。マージンはボーダーの外側の余白です。次の例では、カードの外側に適切なマージンを設定しています。

.card {
background-color: #fff;
width: 240px;
border: 1px solid #bbb;
border-radius: 8px;
margin: 8px;
}

marginプロパティを設定したカード

上下左右の全てではなく、特定の方向のみにマージンを設定したい場合はどうでしょうか。

上側だけにマージンを設定したい場合は、margin-topプロパティを使用します。次の例では、価格表示の上側とボタンの上側にマージンを設定しています。

.price {
font-size: 20px;
margin-top: 8px;
}

.button {
background-color: #0d6efd;
color: #fff;
font-size: 16px;
width: 100%;
border: none;
border-radius: 8px;
margin-top: 16px;
}

内部の要素にmargin-topプロパティを設定したカード

同様に、margin-bottom, margin-left, margin-rightプロパティを使用すると、それぞれ下側・左側・右側のみにマージンを設定することができます。

marginのみならず、paddingborderなどについても同様です。

パディング

paddingプロパティを使って、パディングと呼ばれる余白を設定することができます。パディングはボーダーの内側の余白です。

次の例では、カードの内側とボタンの内側にパディングを設定しています。

.card {
background-color: #fff;
width: 240px;
border: 1px solid #bbb;
border-radius: 8px;
margin: 8px;
padding: 24px;
}
.button {
background-color: #0d6efd;
color: #fff;
font-size: 16px;
width: 100%;
border: none;
border-radius: 8px;
margin-top: 16px;
padding: 8px;
}

paddingプロパティを設定したカード

フレックスボックス

現在は3枚のカードが縦に並んでいますが、これを横に並ぶようにすることを考えます。

フレックスボックスを使用すると、要素を柔軟にレイアウトすることができます。フレックスボックスを使用するには、レイアウトしたい要素の親要素のdisplayプロパティにflexを指定します。フレックスボックスでレイアウトされた要素は、デフォルトで横並びになります。

次の例では、カードの親要素のdisplayプロパティにflexを指定し、カードが横並びになるようにしています。

#container {
display: flex;
}

親要素にdisplay: flex;を設定したカード

これまでは、カードどうしの間隔を空けるために各カードにマージンを設定していました。しかし、フレックスボックスを使う場合は、この目的により適したgapプロパティを利用できます。gapプロパティは、子要素であるカード側ではなく、親要素のコンテナ側で設定します。このプロパティを使うと、要素と要素の間にのみ間隔が作られ、端の要素の外側には余白がつきません。

次の例では、カードのmarginプロパティを削除し、親要素にgapプロパティを指定しています。

.card {
background-color: #fff;
width: 240px;
border: 1px solid #bbb;
border-radius: 8px;
/* margin: 8px; を削除 */
padding: 24px;
}
#container {
display: flex;
gap: 16px;
}

flex-directionプロパティ

フレックスボックスによるレイアウトの方向を変更するには、flex-directionプロパティを使用します。rowを指定すれば水平に、columnを指定すれば垂直にレイアウトされます。

先ほど、display: flex;を指定しただけでカードが横並びになったのは、このプロパティのデフォルト値がrowであるためです。

実際に親要素のflex-directionプロパティをcolumnに指定すると、カードが縦に並ぶことが確認できます。

親要素にflex-direction: column;を設定したカード

justify-contentプロパティ

フレックスボックスでは、justify-contentプロパティを使うことで、flex-directionプロパティで指定した方向のレイアウトを制御することができます。

次の例では、justify-contentプロパティをcenterに指定することで、カードを水平方向の中央に配置しています。

#container {
display: flex;
gap: 16px;
justify-content: center;
}

親要素にjustify-content: center;を設定したカード

他のレイアウト方法も試してみましょう。

準備として、カードのプラン名の横に「詳細」のリンクを設置します。<div class="plan">Free</div>のようになっていた部分を次のように変更し、リンクにはボタンと同じ色を適用します。

<div class="card-header">
<div class="plan">Free</div>
<a href="" class="detail">詳細</a>
</div>
.detail {
color: #0d6efd;
}

次の例では、justify-contentプロパティをspace-betweenに指定することで、プラン名とリンクを水平方向の両端に配置しています。

.card-header {
display: flex;
justify-content: space-between;
}

justify-content: space-between;を設定したカードの上部

align-itemsプロパティ

align-itemsプロパティを使うことで、flex-directionプロパティで指定した方向と交差する方向のレイアウトを制御できます。

次の例では、align-itemsプロパティをcenterに指定することで、プラン名とリンクを垂直方向の中央に配置しています。

.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}

内部の要素にalign-items: center;を設定したカード

レスポンシブデザイン

先ほどはフレックスボックスを使ってカードを横並びにすることができましたが、スマートフォンのような画面の幅が狭い端末では、カードを縦に並べた方が見やすくなります。そこで、画面の幅が一定より小さい場合は、カードが縦並びになるようにしていきましょう。

このように、さまざまな画面サイズの端末に対応するデザイン手法はレスポンシブデザインと呼ばれます。

レスポンシブデザインを行っていく準備として、HTMLのhead要素内に次のmeta要素を記述し、スマートフォンなどの端末でも本来の画面サイズで表示が行われるようにしましょう。

index.htmlのhead要素内
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

レスポンシブデザインを実現するための仕組みとして、メディアクエリがあります。メディアクエリを使用すると、画面の幅などの条件によって適用するCSSを切り替えることができます。次のような構文で記述します。

@media (条件) {
/* 条件が真の場合に適用されるスタイル */
}

条件の部分には、例えば「画面幅が800px以下の場合」としたいならばmax-width: 800pxのように指定します。

メディアクエリを使って、画面幅が一定より小さい場合にflex-directionプロパティの値がcolumnとなるようにすることで、カードを縦並びにすることができます。

@media (max-width: 1024px) {
#container {
flex-direction: column;
}
}

縦並びになった場合も、カードが左右中央に表示されるようにしましょう。

この際は、flex-directionプロパティの値がcolumnとなり垂直方向にレイアウトされているため、水平方向のレイアウトを制御するためにはjustify-contentプロパティではなくalign-itemsプロパティを使用する必要があります。

次の例では、align-itemsプロパティをcenterに指定することで、カードを水平方向の中央に配置しています。

@media (max-width: 1024px) {
#container {
flex-direction: column;
align-items: center;
}
}

演習問題

CSSを使って、次のようなウェブサイトのヘッダーを作成しましょう。

  • 画面幅が広い場合は、ナビゲーションメニューが表示されます。
  • 画面幅が狭い場合は、ナビゲーションメニューの代わりにハンバーガーアイコンが表示されるようにします。

HTMLは次のものを使用してください。

index.html
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Site</title>
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<header>
<div class="container">
<div id="logo">MySite</div>
<button id="hamburger">
<img
src="https://raw.githubusercontent.com/ut-code/utcode-learn/main/docs/2-browser-apps/05-css-layout/hamburger.svg"
alt="メニュー"
/>
</button>
<nav>
<ul id="menu">
<li><a href="">HOME</a></li>
<li><a href="">ABOUT</a></li>
<li><a href="">WORKS</a></li>
<li><a href="">CONTACT</a></li>
</ul>
</nav>
</div>
</header>
</body>
</html>

CSSは次のものをベースに、必要な箇所を記述してください。

style.css
body {
margin: 0;
background-color: #fff;
}

header ul {
margin: 0;
padding: 0;
list-style: none; /* リストのマーカー(•など)を非表示にする */
}

#menu a {
text-decoration: none; /* リンクの下線を消す */
color: #777;
font-size: 14px;
}

#logo {
font-weight: bold; /* 太字にする */
font-size: 24px;
}

#hamburger {
display: none;
width: 40px;
height: 40px;
border: none;
background: none;
padding: 0;
cursor: pointer; /* マウスカーソルをポインタにする */
}

/* ここから下を変更してください。 */

header {
background-color: #fff;
/* ここで適切な境界線を設定する */
}

.container {
display: flex;
/* ここで適切なレイアウトを設定する */
}

#menu {
display: flex;
/* ここで適切なレイアウトを設定する */
}

@media (max-width: 768px) {
#hamburger {
display: flex;
}
/* ここで適切な設定を行う */
}
ヒント

displayプロパティにnoneを指定すると、要素が表示されなくなります。

解答例
style.css
body {
margin: 0;
background-color: #fff;
}

header ul {
margin: 0;
padding: 0;
list-style: none;
}

#menu a {
text-decoration: none;
color: #777;
font-size: 14px;
}

#logo {
font-weight: bold;
font-size: 24px;
}

#hamburger {
display: none;
width: 40px;
height: 40px;
border: none;
background: none;
padding: 0;
cursor: pointer;
}

header {
background-color: #fff;
border-bottom: 1px solid #eee;
}

.container {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 24px;
}

#menu {
display: flex;
gap: 32px;
}

@media (max-width: 768px) {
#hamburger {
display: flex;
}

nav {
display: none;
}
}