シリーズ ゼロからWebサイトを作ろう! 第4回 / 全10回

CSSの基本 ―
サイトに"見た目"を与えよう

HTMLで骨組みを作り、コンテンツを入れ終えたcafé SOELのサイト。今回はいよいよCSSを導入して、色、フォントサイズ、余白を与えていきます。保存してブラウザをリロードした瞬間、見た目が一変する感動をぜひ味わってください。

前回のおさらい

📖 前回のおさらい
  • café SOELの全セクション(ヘッダー〜フッター)のHTMLを書き上げた
  • class 属性を使い、CSSでスタイルを当てるための「名札」を各要素に付けた
  • <img> 要素で画像を配置し、<dl> で店舗情報を構造化した

前回のコードがブラウザに表示できていれば、今回の内容に進む準備は完了です。

今回のゴール

🎯 今回のゴール
  • CSSの基本構文(セレクタ・プロパティ・値)を理解する
  • CSS変数を使ってサイトの配色を一元管理する
  • ボックスモデルの仕組みを理解する
  • café SOELに色・フォントサイズ・余白を与え、ヒーローセクションを全画面表示にする
👀 この回の完成イメージ
今回の内容を終えると、サイトはこのような状態になります。先に完成形を確認しておきたい方はこちらをご覧ください。
第4回の完成イメージを見る →

前回まで黒い文字と素の画像が並んでいただけのHTMLが、今回でぐっと「サイトらしく」なります。ただしパーツの横並び(レイアウト)はまだ行いません。それは次回のFlexboxで学びます。今回はまず「色」「文字」「余白」の基礎を固めましょう。

CSSって何?

CSSは Cascading Style Sheets の略で、HTMLに「見た目」を与えるための言語です。

前回までの講座で家の骨組み(HTML)を作りました。今回からは、壁を塗り、床材を選び、照明を整えていく作業です。HTMLが家の構造を決めるなら、CSSは内装と外装を決める。この役割分担がWeb制作の基本です。

CSSでできることは多岐にわたります。文字の色やサイズ、背景色、余白、角の丸み、画像の表示方法……。この講座を通して少しずつ覚えていきますが、今回はその中でも最も基本的な部分を扱います。

HTMLが「何を伝えるか」を決め、CSSが「どう見せるか」を決める。この分業を守ることが、きれいなコードへの第一歩。

CSSの3つの書き方

CSSを書く場所は3種類あります。結論から言うと、この講座では3つ目の「外部ファイル」を使いますが、他の2つも知っておきましょう。

① インラインスタイル

HTML要素の style 属性に直接書く方法です。

❌ あまり推奨されない書き方
<p style="color: red; font-size: 20px;">赤い文字</p>

手軽ですが、HTMLの中にスタイルが混ざって読みにくくなります。要素が増えるとメンテナンスが大変なので、基本的には使いません。

② <style> タグ

HTMLの <head> 内に <style> タグを書いて、その中にCSSを記述する方法です。

index.html の head 内に書く場合
<style>
  p {
    color: red;
    font-size: 20px;
  }
</style>

1つのHTMLファイル内で完結するときには使えますが、ページが増えたときにスタイルを使い回せません。

③ 外部CSSファイル(推奨)

CSSを別のファイルに書いて、HTMLから読み込む方法です。この講座ではこの方法を使います。

index.html の head 内
<link rel="stylesheet" href="css/style.css">

HTMLとCSSが完全に分離されるので、コードが読みやすく、複数のページで同じスタイルを共有できます。現場でもこの方法が標準です。

💡 KANONのワンポイント
私が独学で始めたころは、インラインスタイルで色を変えるのが楽しくて何でも style 属性に書いていました。でも後から「全部の文字の色を変えたい」となったとき、一つずつ直すはめに……。外部CSSにしておけば、1箇所変えるだけで全ページに反映されます。最初から外部ファイルに書く習慣をつけましょう。

CSSファイルを作ってHTMLにリンクしよう

1

style.css を作成する

VS Codeの左サイドバーで css フォルダを右クリックし、「新しいファイル」を選択します。ファイル名は style.css と入力してください。

📁 現在のフォルダ構成
cafe-soel/
├── index.html
├── css/
│   └── style.css    ← 今回作成!
├── img/
│   ├── hero.jpg
│   ├── ...
└── js/
2

index.html に link タグを追加する

index.html<head> 内にある <title> の直前に、次の1行を追加してください。

index.html — head 部分
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="css/style.css">  <!-- ← この行を追加 -->
  <title>café SOEL — そよぐ光と、ひと息つくひととき</title>
</head>

これでHTMLとCSSがつながりました。 style.css に書いたスタイルが、自動的にページに反映されるようになります。まだ中身は空なので見た目は変わりませんが、ここからどんどん書いていきますよ。

CSSの基本構文

CSSの書き方はとてもシンプルです。「どの要素に」「何を」「どうするか」を指定する、3つのパーツで成り立っています。

CSSの基本構文
セレクタ {
  プロパティ: ;
}

セレクタは「どの要素にスタイルを当てるか」を指定します。プロパティは「何を変えるか」(色、サイズ、余白など)。は「どう変えるか」(赤、20px、10pxなど)。そして末尾のセミコロン ; を忘れずに。

たとえば「すべての段落(p)の文字色を灰色にする」なら、こう書きます。

css/style.css
p {
  color: #6b6b6b;
}

セレクタの種類

セレクタにはいくつかの種類がありますが、今回使うのは3つです。

要素セレクタは、HTMLタグ名をそのまま書きます。そのタグすべてにスタイルが当たります。

要素セレクタ
body {
  font-size: 16px;
}

クラスセレクタは、前回付けた class 属性を目印にする方法です。クラス名の前にドット(.)を付けます。

クラスセレクタ
.hero-title {
  font-size: 52px;
}

子孫セレクタは、ある要素の中にある要素だけを対象にする書き方です。セレクタをスペースで区切ります。

子孫セレクタ
.menu-card-body p {
  font-size: 14px;
}

前回 class 属性を丁寧に付けたのは、まさにこのため。クラスセレクタを使えば、特定の要素だけにピンポイントでスタイルを当てられます。

CSS変数で色を一元管理する

café SOELのサイトでは、同じ色を何度も使います。背景色、文字色、アクセントカラー……。これを毎回 #2c2c2c のようなカラーコードで書いていたら、あとで配色を変えたくなったとき大変ですよね。

そこで使うのが CSS変数(カスタムプロパティ)です。 :root セレクタの中に「変数名 → 色コード」を定義しておけば、あとは変数名を使い回すだけ。色を変えたくなったら、定義を1箇所変えるだけで全体に反映されます。

では、 style.css の一番上に以下を書いてください。これがcafé SOELの配色とレイアウトの基本設定になります。

css/style.css — CSS変数の定義
/* ---------- CSS Custom Properties ---------- */
:root {
  --color-bg: #ffffff;
  --color-bg-soft: #faf9f7;
  --color-bg-accent: #f5f0eb;
  --color-text: #2c2c2c;
  --color-text-light: #6b6b6b;
  --color-text-muted: #999999;
  --color-accent: #8b7355;
  --color-accent-light: #c4a882;
  --color-border: #e8e4df;
  --color-white: #ffffff;
  --color-black: #1a1a1a;

  --section-padding: 120px;
  --container-width: 1200px;
  --container-padding: 24px;
}

:root はHTML文書の最上位要素を表すセレクタで、ここに書いた変数はページ全体で使えます。変数名は -- で始めるのがルールです。

使うときは var(--変数名) と書きます。たとえば color: var(--color-text); のように。このあとのコードで実際に使っていきますね。

📌 覚えておこう
CSS変数を使う最大のメリットは「変更に強いこと」です。たとえば、アクセントカラーをブラウンから他の色に変えたくなったら --color-accent の値を1箇所書き換えるだけ。サイト全体に自動で反映されます。プロの現場でも欠かせないテクニックです。

ボックスモデルを理解しよう

CSSでレイアウトを組む前に、ひとつ大事な仕組みを知っておきましょう。HTMLのすべての要素は「箱(ボックス)」として扱われます。そしてその箱には、内側から順に4つの領域があります。

▶ Live Demo — ボックスモデル
margin(外側の余白)
border(枠線)
padding(内側の余白)
content
(コンテンツ)

content(コンテンツ)はテキストや画像など、要素の中身そのもの。padding(パディング)はコンテンツの周りの内側の余白。border(ボーダー)は枠線。margin(マージン)は要素と要素の間の外側の余白です。

ここで重要なのが box-sizing というプロパティです。デフォルトでは、CSSで指定した width は content の幅だけを指します。そこに padding や border が足されるので、実際の表示サイズが計算しにくくなります。

box-sizing: border-box を指定すると、 width に padding と border が含まれるようになります。「幅を300pxにしたら、見た目も300px」。直感的で、ほぼすべてのWeb制作で使われる設定です。

リセットCSSと基本設定を書こう

ブラウザには、何もCSSを書かなくても適用される「デフォルトスタイル」があります。たとえば <h1> が大きな太字になったり、 <ul> にリスト記号がついたりするのは、ブラウザのデフォルトスタイルのおかげです。

ただ、このデフォルトスタイルはブラウザごとに微妙に異なります。そこで最初に「リセット」をかけて、まっさらな状態から自分でスタイルを組み立てるのが定番のやり方です。

CSS変数の下に、以下のリセットと基本設定を追加してください。

css/style.css — リセット&基本設定
/* ---------- Reset & Base ---------- */
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: 80px;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI',
               'Hiragino Kaku Gothic ProN', 'Noto Sans JP', sans-serif;
  font-weight: 400;
  font-size: 16px;
  line-height: 1.9;
  color: var(--color-text);
  background-color: var(--color-bg);
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  color: inherit;
  text-decoration: none;
}

ul, ol {
  list-style: none;
}

*(アスタリスク)は「すべての要素」を指すセレクタです。これで全要素の margin と padding を 0 にリセットし、 box-sizing: border-box を適用しています。

scroll-behavior: smooth は、ナビゲーションのページ内リンクをクリックしたとき、カクッとジャンプするのではなく滑らかにスクロールする設定です。前回作ったページ内リンクが、これだけでぐっと心地よくなります。

bodyfont-family にはシステムフォント(OSに最初から入っているフォント)を指定しています。左から順に、ブラウザが使えるフォントを探して適用してくれます。Macなら「ヒラギノ角ゴ」、Windowsなら「Noto Sans JP」や「Segoe UI」が使われるイメージです。

imgmax-width: 100% を設定することで、画像が親要素からはみ出さなくなります。前回、画像が巨大に表示されていた問題がこれだけで解決します。

ここまで書いたら保存してブラウザを確認してみましょう。リスト記号が消え、余白がリセットされ、画像がページ幅に収まっているはずです。

⚠️ よくあるミス
保存してもブラウザの表示が変わらない場合、<link> タグの href が正しいか確認してください。 href="css/style.css" のパスが、実際のフォルダ構成と一致していないと読み込めません。Live Server を使っていれば自動更新されますが、ブラウザのキャッシュが残っている場合は Ctrl + Shift + R(Macは Cmd + Shift + R)で強制リロードしてみてください。

セクションの共通スタイルを書こう

リセットが終わったので、ここからはcafé SOELの各セクションにスタイルを当てていきます。まずは複数のセクションで使い回す共通パーツから。

css/style.css — 共通スタイル
/* ---------- Utility ---------- */
.section {
  padding: var(--section-padding) var(--container-padding);
}

.section-label {
  display: inline-block;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--color-accent);
  margin-bottom: 16px;
}

.section-heading {
  font-size: clamp(24px, 4vw, 36px);
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.02em;
  color: var(--color-black);
  margin-bottom: 20px;
}

.section-header {
  text-align: center;
  max-width: 600px;
  margin: 0 auto 60px;
}

.section-desc {
  font-size: 15px;
  color: var(--color-text-light);
  line-height: 1.8;
}

clamp(24px, 4vw, 36px) は便利な関数で、「最小24px、画面幅に応じて4vw、最大36px」という意味です。画面が大きければ文字が大きくなり、小さければ小さくなる。レスポンシブ対応の下準備にもなっています。

margin: 0 auto 60px は「上の余白0、左右は自動(=中央寄せ)、下の余白60px」。ブロック要素を中央に配置する定番テクニックです。

ヘッダーのスタイルを書こう

ヘッダーはページの最上部に固定される「ナビゲーションバー」です。スクロールしても常に画面上に見えているように、 position: fixed を使います。

css/style.css — ヘッダー
/* ---------- Header ---------- */
.header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
  background-color: var(--color-white);
  border-bottom: 1px solid var(--color-border);
}

.header-inner {
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 0 var(--container-padding);
  height: 72px;
}

.logo img {
  height: 32px;
  width: auto;
}

.nav-link {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--color-text);
}

position: fixed は要素をブラウザの画面に固定します。 top: 0; left: 0; width: 100%; で画面上部いっぱいに広がるヘッダーになります。 z-index: 100 は重なり順を指定するプロパティで、大きい数値ほど手前に表示されます。ヒーローの画像や他のセクションの上にヘッダーが被さるようにしています。

ロゴとナビゲーションがまだ横並びにならず、縦に積まれていますよね。横並びにするには Flexbox が必要で、それは次回の第5回で学びます。今は縦に並んでいるのが正しい状態です。

ヒーローセクションを仕上げよう

ここが今回のハイライトです。ヒーローセクションを画面いっぱいに表示し、画像の上に半透明のオーバーレイをかけ、テキストを中央に配置します。

css/style.css — ヒーロー
/* ---------- Hero ---------- */
.hero {
  position: relative;
  height: 100vh;
  min-height: 600px;
  max-height: 1000px;
  overflow: hidden;
}

.hero-image {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.hero-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero-image::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.15) 0%,
    rgba(0, 0, 0, 0.35) 100%
  );
}

.hero-content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  text-align: center;
  color: var(--color-white);
  padding: 0 var(--container-padding);
}

.hero-sub {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 4px;
  text-transform: uppercase;
  margin-bottom: 20px;
  opacity: 0.9;
}

.hero-title {
  font-size: clamp(28px, 5vw, 52px);
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: 0.06em;
  margin-bottom: 40px;
  text-shadow: 0 2px 20px rgba(0, 0, 0, 0.2);
}

.hero-cta {
  display: inline-block;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--color-white);
  padding: 12px 36px;
}

順番に見ていきましょう。

height: 100vhvh はビューポート(ブラウザの表示領域)の高さの1%を意味する単位です。 100vh で「画面の高さいっぱい」になります。

.hero-imageposition: absoluteinset: 0 を指定することで、画像を親要素( .hero )の全面に広げています。 inset: 0top: 0; right: 0; bottom: 0; left: 0; のショートハンドです。

object-fit: cover は画像のアスペクト比を維持しつつ、枠いっぱいに拡大するプロパティです。写真が枠の形に合わせてトリミングされるイメージですね。

::after 疑似要素で半透明のグラデーションをかけています。これが「オーバーレイ」で、画像の上に薄い暗幕をかけて、白い文字を読みやすくするテクニックです。

💡 KANONのワンポイント
.hero-content の中央配置に position: absolutetransform: translate(-50%, -50%) を使いました。「要素を上から50%・左から50%の位置に置いて、自分自身の大きさの半分だけ戻す」という仕組みで中央に来ます。少しトリッキーですが、position だけで中央配置する伝統的な方法です。実は次回学ぶFlexboxを使えば、もっとシンプルに書けます。お楽しみに。

残りのセクションにスタイルを当てよう

ヒーローが仕上がったので、残りのセクションにも基本的なスタイルを付けていきます。まだ Flexbox を使わないので横並びにはなりませんが、色やフォントサイズ、余白が整うだけでだいぶ印象が変わります。

css/style.css — コンセプト・メニュー・ギャラリー・アクセス・フッター
/* ---------- Concept ---------- */
.concept {
  background-color: var(--color-bg);
}

.concept-inner {
  max-width: var(--container-width);
  margin: 0 auto;
}

.concept-image {
  border-radius: 12px;
  overflow: hidden;
}

.concept-text p {
  font-size: 15px;
  line-height: 2;
  color: var(--color-text-light);
  margin-bottom: 16px;
}

.concept-text p:last-child {
  margin-bottom: 0;
}

/* ---------- Menu ---------- */
.menu {
  background-color: var(--color-bg-soft);
}

.menu-card-body {
  padding: 24px;
}

.menu-card-title {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 1px;
  margin-bottom: 8px;
  color: var(--color-black);
}

.menu-card-desc {
  font-size: 14px;
  line-height: 1.8;
  color: var(--color-text-light);
  margin-bottom: 12px;
}

.menu-card-price {
  font-size: 18px;
  font-weight: 600;
  color: var(--color-accent);
  letter-spacing: 1px;
}

/* ---------- Gallery ---------- */
.gallery {
  background-color: var(--color-bg);
}

/* ---------- Access ---------- */
.access {
  background-color: var(--color-bg-soft);
}

.access-inner {
  max-width: var(--container-width);
  margin: 0 auto;
}

.access-image {
  border-radius: 12px;
  overflow: hidden;
}

.info-list {
  margin-top: 12px;
}

.info-item {
  padding: 16px 0;
  border-bottom: 1px solid var(--color-border);
}

.info-item:last-child {
  border-bottom: none;
}

.info-item dt {
  font-size: 13px;
  font-weight: 500;
  color: var(--color-text-muted);
  letter-spacing: 0.5px;
  margin-bottom: 4px;
}

.info-item dd {
  font-size: 15px;
  line-height: 1.8;
  color: var(--color-text);
}

.info-item dd a {
  color: var(--color-accent);
}

/* ---------- Footer ---------- */
.footer {
  background-color: var(--color-black);
  color: var(--color-white);
  padding: 60px var(--container-padding);
}

.footer-inner {
  max-width: var(--container-width);
  margin: 0 auto;
}

.footer-logo img {
  height: 24px;
  width: auto;
  filter: brightness(0) invert(1);
  opacity: 0.8;
}

.footer-nav a {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

.footer-copy {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.35);
  letter-spacing: 0.5px;
}

border-radius: 12px は角を丸くするプロパティです。 overflow: hidden と組み合わせることで、画像の角もきれいに丸くなります。

フッターでは filter: brightness(0) invert(1) というテクニックを使っています。これは画像を一度真っ黒にしてから反転させることで、白い画像に変えるフィルターです。黒い背景の上にロゴを白く表示するためです。

rgba(255, 255, 255, 0.5) は「白の50%透明」を意味します。フッターのナビリンクを少し控えめな色にして、メインコンテンツとの差を出しています。

ここまでの全体を確認しよう

CSSファイルを保存して、ブラウザをリロードしてみましょう。さっきまで素朴だったHTMLが、一気に変わったはずです。

👀 この回の完成イメージ
ここまでのコードをブラウザで開くと、このような表示になります。
第4回の完成イメージを見る →

ヒーロー画像が画面いっぱいに広がり、「そよぐ光と、ひと息つくひととき。」のキャッチコピーが中央に。セクションごとに背景色が交互に変わり、フッターはダークな配色に。だいぶサイトらしくなりましたよね。

まだヘッダーのナビゲーションが横に並んでいなかったり、コンセプトの画像とテキストが縦に並んでいたりしますよね。それは正常です。パーツを"横に並べる"にはレイアウトの技術が必要で、それは次回学ぶFlexboxで解決します。あなたの画面でも同じように見えていますか?

ここまでの index.htmlcss/style.css の全コードを掲載します。もしうまくいかない場合は、このコードをまるごとコピーして貼り付けてリカバリーしてください。

index.html(第4回完成時点)
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="css/style.css">
  <title>café SOEL — そよぐ光と、ひと息つくひととき</title>
</head>
<body>

  <!-- ========== HEADER ========== -->
  <header class="header" id="top">
    <div class="header-inner">
      <a href="#top" class="logo">
        <img src="img/logo.png" alt="café SOEL" width="160" height="40">
      </a>
      <nav aria-label="メインナビゲーション">
        <ul class="nav-list">
          <li><a href="#concept" class="nav-link">Concept</a></li>
          <li><a href="#menu" class="nav-link">Menu</a></li>
          <li><a href="#gallery" class="nav-link">Gallery</a></li>
          <li><a href="#access" class="nav-link">Access</a></li>
        </ul>
      </nav>
    </div>
  </header>

  <main>

    <!-- ========== HERO ========== -->
    <section class="hero" id="hero">
      <div class="hero-image">
        <img src="img/hero.jpg" alt="café SOELの店内。大きな窓から自然光が差し込む開放的な空間" width="1920" height="1080">
      </div>
      <div class="hero-content">
        <p class="hero-sub">Natural Light &amp; Coffee</p>
        <h1 class="hero-title">そよぐ光と、<br>ひと息つくひととき。</h1>
        <a href="#concept" class="hero-cta">Scroll</a>
      </div>
    </section>

    <!-- ========== CONCEPT ========== -->
    <section class="concept section" id="concept">
      <div class="concept-inner">
        <div class="concept-image">
          <img src="img/concept.jpg" alt="木のテーブルの上に置かれたハンドドリップコーヒーと陶器のカップ" width="1200" height="800">
        </div>
        <div class="concept-text">
          <span class="section-label">Concept</span>
          <h2 class="section-heading">ひかりと、木と、<br>一杯のコーヒーと。</h2>
          <p>café SOEL(カフェ ソエル)は、「そよぐ光」をイメージした造語から名づけました。</p>
          <p>大きな窓から差し込む自然光、ナチュラルな木のぬくもり、丁寧に淹れた一杯のコーヒー。忙しい日常からすこしだけ離れて、穏やかな時間を過ごしていただける場所でありたいと思っています。</p>
          <p>素材の味を大切にしたフードとドリンクを、心を込めてお届けします。</p>
        </div>
      </div>
    </section>

    <!-- ========== MENU ========== -->
    <section class="menu section" id="menu">
      <div class="section-header">
        <span class="section-label">Menu</span>
        <h2 class="section-heading">こだわりのメニュー</h2>
        <p class="section-desc">素材を活かしたシンプルなおいしさを、丁寧にお届けします。</p>
      </div>
      <div class="menu-grid">
        <article class="menu-card">
          <div class="menu-card-image">
            <img src="img/menu-coffee.jpg" alt="ハンドドリップで淹れたコーヒー" width="800" height="800">
          </div>
          <div class="menu-card-body">
            <h3 class="menu-card-title">Hand Drip Coffee</h3>
            <p class="menu-card-desc">産地ごとに異なる豆の個性を引き出す、一杯ずつ丁寧なハンドドリップ。</p>
            <span class="menu-card-price">¥550</span>
          </div>
        </article>
        <article class="menu-card">
          <div class="menu-card-image">
            <img src="img/menu-latte.jpg" alt="シンプルなラテアートが施されたカフェラテ" width="800" height="800">
          </div>
          <div class="menu-card-body">
            <h3 class="menu-card-title">Café Latte</h3>
            <p class="menu-card-desc">まろやかなミルクとエスプレッソのバランス。シンプルなラテアートを添えて。</p>
            <span class="menu-card-price">¥600</span>
          </div>
        </article>
        <article class="menu-card">
          <div class="menu-card-image">
            <img src="img/menu-cake.jpg" alt="素朴で美しいケーキ" width="800" height="800">
          </div>
          <div class="menu-card-body">
            <h3 class="menu-card-title">Seasonal Cake</h3>
            <p class="menu-card-desc">季節のフルーツを使った、素朴だけど美しいケーキ。コーヒーとの相性も抜群です。</p>
            <span class="menu-card-price">¥650</span>
          </div>
        </article>
        <article class="menu-card">
          <div class="menu-card-image">
            <img src="img/menu-sandwich.jpg" alt="断面が美しいサンドイッチ" width="800" height="800">
          </div>
          <div class="menu-card-body">
            <h3 class="menu-card-title">SOEL Sandwich</h3>
            <p class="menu-card-desc">新鮮な野菜とハム、自家製ソースをはさんだボリュームのあるサンドイッチ。</p>
            <span class="menu-card-price">¥900</span>
          </div>
        </article>
      </div>
    </section>

    <!-- ========== GALLERY ========== -->
    <section class="gallery section" id="gallery">
      <div class="section-header">
        <span class="section-label">Gallery</span>
        <h2 class="section-heading">店内の様子</h2>
        <p class="section-desc">自然光と木のぬくもりに包まれた、穏やかな空間。</p>
      </div>
      <div class="gallery-grid">
        <div class="gallery-item gallery-item--large">
          <img src="img/interior-01.jpg" alt="大きな窓から光が差し込む窓際の席" width="1200" height="800">
        </div>
        <div class="gallery-item">
          <img src="img/interior-02.jpg" alt="木のカウンターとペンダントライト" width="1200" height="800">
        </div>
        <div class="gallery-item">
          <img src="img/exterior.jpg" alt="白い外壁と黒フレームの窓が特徴的な外観" width="1600" height="1000">
        </div>
      </div>
    </section>

    <!-- ========== ACCESS ========== -->
    <section class="access section" id="access">
      <div class="access-inner">
        <div class="access-image">
          <img src="img/exterior.jpg" alt="café SOELの外観" width="1600" height="1000">
        </div>
        <div class="access-info">
          <span class="section-label">Access</span>
          <h2 class="section-heading">店舗情報</h2>
          <dl class="info-list">
            <div class="info-item">
              <dt>住所</dt>
              <dd>〒156-0054 東京都世田谷区桜丘町3-12-8</dd>
            </div>
            <div class="info-item">
              <dt>営業時間</dt>
              <dd>
                平日 10:00 – 19:00<br>
                土日 9:00 – 19:00
              </dd>
            </div>
            <div class="info-item">
              <dt>定休日</dt>
              <dd>毎週水曜日</dd>
            </div>
            <div class="info-item">
              <dt>電話</dt>
              <dd><a href="tel:03-0000-0000">03-0000-0000</a></dd>
            </div>
            <div class="info-item">
              <dt>アクセス</dt>
              <dd>小田急線 千歳船橋駅より徒歩8分</dd>
            </div>
          </dl>
        </div>
      </div>
    </section>

  </main>

  <!-- ========== FOOTER ========== -->
  <footer class="footer">
    <div class="footer-inner">
      <a href="#top" class="footer-logo">
        <img src="img/logo.png" alt="café SOEL" width="120" height="30">
      </a>
      <ul class="footer-nav">
        <li><a href="#concept">Concept</a></li>
        <li><a href="#menu">Menu</a></li>
        <li><a href="#gallery">Gallery</a></li>
        <li><a href="#access">Access</a></li>
      </ul>
      <p class="footer-copy">&copy; 2025 café SOEL. All rights reserved.</p>
    </div>
  </footer>

</body>
</html>
css/style.css(第4回完成時点)
/* ===================================
   café SOEL — Style Sheet
   第4回時点:基本CSS
   =================================== */

/* ---------- CSS Custom Properties ---------- */
:root {
  --color-bg: #ffffff;
  --color-bg-soft: #faf9f7;
  --color-bg-accent: #f5f0eb;
  --color-text: #2c2c2c;
  --color-text-light: #6b6b6b;
  --color-text-muted: #999999;
  --color-accent: #8b7355;
  --color-accent-light: #c4a882;
  --color-border: #e8e4df;
  --color-white: #ffffff;
  --color-black: #1a1a1a;

  --section-padding: 120px;
  --container-width: 1200px;
  --container-padding: 24px;
}

/* ---------- Reset & Base ---------- */
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: 80px;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI',
               'Hiragino Kaku Gothic ProN', 'Noto Sans JP', sans-serif;
  font-weight: 400;
  font-size: 16px;
  line-height: 1.9;
  color: var(--color-text);
  background-color: var(--color-bg);
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  color: inherit;
  text-decoration: none;
}

ul, ol {
  list-style: none;
}

/* ---------- Utility ---------- */
.section {
  padding: var(--section-padding) var(--container-padding);
}

.section-label {
  display: inline-block;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--color-accent);
  margin-bottom: 16px;
}

.section-heading {
  font-size: clamp(24px, 4vw, 36px);
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.02em;
  color: var(--color-black);
  margin-bottom: 20px;
}

.section-header {
  text-align: center;
  max-width: 600px;
  margin: 0 auto 60px;
}

.section-desc {
  font-size: 15px;
  color: var(--color-text-light);
  line-height: 1.8;
}

/* ---------- Header ---------- */
.header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
  background-color: var(--color-white);
  border-bottom: 1px solid var(--color-border);
}

.header-inner {
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 0 var(--container-padding);
  height: 72px;
}

.logo img {
  height: 32px;
  width: auto;
}

.nav-link {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--color-text);
}

/* ---------- Hero ---------- */
.hero {
  position: relative;
  height: 100vh;
  min-height: 600px;
  max-height: 1000px;
  overflow: hidden;
}

.hero-image {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.hero-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero-image::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.15) 0%,
    rgba(0, 0, 0, 0.35) 100%
  );
}

.hero-content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  text-align: center;
  color: var(--color-white);
  padding: 0 var(--container-padding);
}

.hero-sub {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 4px;
  text-transform: uppercase;
  margin-bottom: 20px;
  opacity: 0.9;
}

.hero-title {
  font-size: clamp(28px, 5vw, 52px);
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: 0.06em;
  margin-bottom: 40px;
  text-shadow: 0 2px 20px rgba(0, 0, 0, 0.2);
}

.hero-cta {
  display: inline-block;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--color-white);
  padding: 12px 36px;
}

/* ---------- Concept ---------- */
.concept {
  background-color: var(--color-bg);
}

.concept-inner {
  max-width: var(--container-width);
  margin: 0 auto;
}

.concept-image {
  border-radius: 12px;
  overflow: hidden;
}

.concept-text p {
  font-size: 15px;
  line-height: 2;
  color: var(--color-text-light);
  margin-bottom: 16px;
}

.concept-text p:last-child {
  margin-bottom: 0;
}

/* ---------- Menu ---------- */
.menu {
  background-color: var(--color-bg-soft);
}

.menu-card-body {
  padding: 24px;
}

.menu-card-title {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 1px;
  margin-bottom: 8px;
  color: var(--color-black);
}

.menu-card-desc {
  font-size: 14px;
  line-height: 1.8;
  color: var(--color-text-light);
  margin-bottom: 12px;
}

.menu-card-price {
  font-size: 18px;
  font-weight: 600;
  color: var(--color-accent);
  letter-spacing: 1px;
}

/* ---------- Gallery ---------- */
.gallery {
  background-color: var(--color-bg);
}

/* ---------- Access ---------- */
.access {
  background-color: var(--color-bg-soft);
}

.access-inner {
  max-width: var(--container-width);
  margin: 0 auto;
}

.access-image {
  border-radius: 12px;
  overflow: hidden;
}

.info-list {
  margin-top: 12px;
}

.info-item {
  padding: 16px 0;
  border-bottom: 1px solid var(--color-border);
}

.info-item:last-child {
  border-bottom: none;
}

.info-item dt {
  font-size: 13px;
  font-weight: 500;
  color: var(--color-text-muted);
  letter-spacing: 0.5px;
  margin-bottom: 4px;
}

.info-item dd {
  font-size: 15px;
  line-height: 1.8;
  color: var(--color-text);
}

.info-item dd a {
  color: var(--color-accent);
}

/* ---------- Footer ---------- */
.footer {
  background-color: var(--color-black);
  color: var(--color-white);
  padding: 60px var(--container-padding);
}

.footer-inner {
  max-width: var(--container-width);
  margin: 0 auto;
}

.footer-logo img {
  height: 24px;
  width: auto;
  filter: brightness(0) invert(1);
  opacity: 0.8;
}

.footer-nav a {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

.footer-copy {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.35);
  letter-spacing: 0.5px;
}

今回のまとめ

  • CSSはHTMLに「見た目」を与える言語。書き方は3種類あるが、外部CSSファイルを使うのが現場の標準
  • CSSの基本構文は「セレクタ { プロパティ: 値; }」。セレクタには要素セレクタ・クラスセレクタ・子孫セレクタがある
  • CSS変数(カスタムプロパティ)を :root に定義することで、色やサイズを一元管理できる
  • ボックスモデルはcontent → padding → border → marginの4層構造。box-sizing: border-box で直感的なサイズ指定ができる
  • リセットCSSでブラウザのデフォルトスタイルを初期化し、自分のスタイルを正確にコントロールできるようにした
  • ヒーローセクションでは 100vhpositionobject-fit: cover、疑似要素によるオーバーレイ、transform による中央配置を使った
  • パーツの横並び(レイアウト)はまだ行っていない。次回のFlexboxで解決する