第5回:CSSレイアウト基礎
🎯 学習目標
- Flexboxの基本概念を理解する
- レスポンシブデザインの重要性を学ぶ
- メディアクエリを使いこなせるようになる
- 2カラムレイアウトを実装できる
📚 導入(5分)
従来のレイアウト手法の問題点
従来のCSSレイアウトでは以下の問題がありました:
/* floatを使ったレイアウト(古い手法) */
.container {
overflow: hidden; /* clearfixのため */
}
.sidebar {
float: left;
width: 300px;
}
.main-content {
float: right;
width: calc(100% - 320px); /* 複雑な計算が必要 */
}
/* クリアフィックスが必要 */
.container::after {
content: "";
display: table;
clear: both;
}問題点:
- 複雑なクリアフィックスが必要
- 垂直中央揃えが困難
- レスポンシブ対応が煩雑
- 等高レイアウトが困難
Flexboxの登場とその利点
Flexbox(Flexible Box Layout)により、これらの問題が解決されました:
/* Flexboxを使ったレイアウト */
.container {
display: flex;
gap: 20px;
}
.sidebar {
width: 300px;
}
.main-content {
flex: 1; /* 残りスペースを占有 */
}利点:
- シンプルな記述
- 自動的な等高レイアウト
- 簡単な垂直中央揃え
- 柔軟なレスポンシブ対応
💡 理論学習(30分)
Flexboxの概念(20分)
display: flexの効果
.flex-container {
display: flex;
}Flexboxを適用すると:
- フレックスコンテナ(親要素)になる
- 子要素がフレックスアイテムになる
- 主軸(main axis)と交差軸(cross axis)が定義される
主軸と交差軸
flex-direction: row; (デフォルト)
┌─────────────────────────────────┐
│ ←───── 主軸(main axis) ─────→ │
│ ┌─────┐ ┌─────┐ ┌─────┐ │ ↑
│ │ A │ │ B │ │ C │ │ │
│ └─────┘ └─────┘ └─────┘ │ │ 交差軸
│ │ │ (cross axis)
└─────────────────────────────────┘ ↓
flex-direction: column;
┌─────────────┐
│ │ ↑
│ ┌─────┐ │ │
│ │ A │ │ │ 主軸
│ └─────┘ │ │ (main axis)
│ │ │
│ ┌─────┐ │ │
│ │ B │ │ │
│ └─────┘ │ ↓
│ │
└─────────────┘
← 交差軸 →コンテナ(親要素)のプロパティ
flex-direction:軸の方向
.container {
display: flex;
/* 主軸の方向を指定 */
flex-direction: row; /* デフォルト:左から右 */
flex-direction: row-reverse; /* 右から左 */
flex-direction: column; /* 上から下 */
flex-direction: column-reverse; /* 下から上 */
}justify-content:主軸方向の配置
.container {
display: flex;
/* 主軸方向の配置 */
justify-content: flex-start; /* 開始点に揃える(デフォルト) */
justify-content: flex-end; /* 終了点に揃える */
justify-content: center; /* 中央に揃える */
justify-content: space-between; /* 両端揃え */
justify-content: space-around; /* 均等配置(両端に半分のスペース) */
justify-content: space-evenly; /* 完全均等配置 */
}justify-content: space-between;
┌─────────────────────────────────┐
│ ┌─┐ ┌─┐ ┌─┐ ┌─┐ │
│ │A│ │B│ │C│ │D│ │
│ └─┘ └─┘ └─┘ └─┘ │
└─────────────────────────────────┘
justify-content: space-around;
┌─────────────────────────────────┐
│ ┌─┐ ┌─┐ ┌─┐ ┌─┐ │
│ │A│ │B│ │C│ │D│ │
│ └─┘ └─┘ └─┘ └─┘ │
└─────────────────────────────────┘align-items:交差軸方向の配置
.container {
display: flex;
height: 200px; /* 高さを指定して効果を確認 */
/* 交差軸方向の配置 */
align-items: stretch; /* 伸縮(デフォルト) */
align-items: flex-start; /* 開始点に揃える */
align-items: flex-end; /* 終了点に揃える */
align-items: center; /* 中央に揃える */
align-items: baseline; /* ベースラインに揃える */
}flex-wrap:折り返し
.container {
display: flex;
/* 折り返しの制御 */
flex-wrap: nowrap; /* 折り返さない(デフォルト) */
flex-wrap: wrap; /* 折り返す */
flex-wrap: wrap-reverse; /* 逆方向に折り返す */
}align-content:複数行の配置(flex-wrap: wrapの場合)
.container {
display: flex;
flex-wrap: wrap;
/* 複数行の配置 */
align-content: flex-start;
align-content: center;
align-content: space-between;
}gap:アイテム間の余白
.container {
display: flex;
gap: 20px; /* 全方向 */
gap: 10px 20px; /* 行 列 */
column-gap: 20px; /* 列方向のみ */
row-gap: 10px; /* 行方向のみ */
}アイテム(子要素)のプロパティ
flex:伸縮の制御
.item {
/* flex-grow flex-shrink flex-basisの一括指定 */
flex: 1; /* 1 1 0% */
flex: 0 0 200px; /* 伸縮なし、幅200px固定 */
flex: 2 1 300px; /* 成長比2、縮小比1、ベース300px */
}
/* 個別指定 */
.item {
flex-grow: 1; /* 余白の分配比率 */
flex-shrink: 1; /* 縮小の比率 */
flex-basis: auto; /* ベースサイズ */
}align-self:個別の交差軸配置
.item {
/* このアイテムだけ個別に配置を変更 */
align-self: flex-start;
align-self: center;
align-self: flex-end;
}order:表示順序の変更
.item1 { order: 2; } /* 2番目に表示 */
.item2 { order: 1; } /* 1番目に表示 */
.item3 { order: 3; } /* 3番目に表示 */レスポンシブデザインの基礎(10分)
viewport metaタグの重要性
<meta name="viewport" content="width=device-width, initial-scale=1.0">この設定により:
- モバイルでも適切なサイズで表示
- ズーム機能の制御
- レスポンシブデザインが正常に動作
相対単位の使い分け
/* 絶対単位(固定サイズ) */
.fixed {
width: 300px; /* 常に300ピクセル */
}
/* 相対単位(可変サイズ) */
.responsive {
width: 50%; /* 親要素の50% */
font-size: 1.2em; /* 親要素のフォントサイズの1.2倍 */
padding: 2rem; /* ルート要素のフォントサイズの2倍 */
height: 50vh; /* ビューポート高さの50% */
width: 80vw; /* ビューポート幅の80% */
}| 単位 | 説明 | 使用場面 |
|---|---|---|
| % | 親要素を基準 | 幅、高さの比率指定 |
| em | 親要素のfont-sizeを基準 | 余白、内部要素のサイズ |
| rem | ルート要素のfont-sizeを基準 | フォントサイズ、統一的な余白 |
| vw | ビューポート幅の1% | レスポンシブな幅 |
| vh | ビューポート高さの1% | フルスクリーン要素 |
| vmin | vwとvhの小さい方 | 正方形を保つ要素 |
| vmax | vwとvhの大きい方 | 画面全体を覆う要素 |
メディアクエリの基本
/* デスクトップファースト */
.container {
width: 1200px; /* デスクトップ */
}
@media (max-width: 1200px) {
.container {
width: 100%; /* タブレット以下 */
}
}
@media (max-width: 768px) {
.container {
padding: 10px; /* モバイル */
}
}
/* モバイルファースト(推奨) */
.container {
width: 100%; /* モバイル */
padding: 10px;
}
@media (min-width: 768px) {
.container {
padding: 20px; /* タブレット以上 */
}
}
@media (min-width: 1200px) {
.container {
width: 1200px; /* デスクトップ */
margin: 0 auto;
}
}🛠️ 実習(50分)
2カラムレイアウトの作成(45分)
HTML構造
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2カラムレイアウト</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<header class="site-header">
<div class="header-container">
<h1 class="site-title">My Blog</h1>
<nav class="main-nav">
<ul class="nav-list">
<li><a href="#" class="nav-link">ホーム</a></li>
<li><a href="#" class="nav-link">記事</a></li>
<li><a href="#" class="nav-link">プロフィール</a></li>
<li><a href="#" class="nav-link">お問い合わせ</a></li>
</ul>
</nav>
</div>
</header>
<div class="page-container">
<!-- メインコンテンツ -->
<main class="main-content">
<article class="article">
<header class="article-header">
<h2 class="article-title">Flexboxの基本</h2>
<time class="article-date">2024年1月29日</time>
</header>
<div class="article-content">
<p>Flexboxは現代のWebデザインに欠かせないレイアウト技術です。</p>
<p>従来のfloatベースのレイアウトと比べて、はるかに柔軟で直感的にレイアウトを作成できます。</p>
<h3>Flexboxの主な利点</h3>
<ul>
<li>簡単な垂直中央揃え</li>
<li>等高カラムの自動実現</li>
<li>柔軟な要素の配置</li>
<li>レスポンシブ対応の簡素化</li>
</ul>
</div>
</article>
<article class="article">
<header class="article-header">
<h2 class="article-title">レスポンシブデザインの重要性</h2>
<time class="article-date">2024年1月28日</time>
</header>
<div class="article-content">
<p>モバイルファーストの時代において、レスポンシブデザインは必須の技術です。</p>
<p>様々なデバイスサイズに対応することで、すべてのユーザーに最適な体験を提供できます。</p>
</div>
</article>
</main>
<!-- サイドバー -->
<aside class="sidebar">
<section class="widget">
<h3 class="widget-title">プロフィール</h3>
<div class="profile">
<img src="https://via.placeholder.com/80" alt="プロフィール画像" class="profile-image">
<p class="profile-text">Web制作を学習中の初心者です。HTML、CSS、JavaScriptを勉強しています。</p>
</div>
</section>
<section class="widget">
<h3 class="widget-title">最新記事</h3>
<ul class="recent-posts">
<li class="recent-post">
<a href="#" class="recent-post-link">Flexboxの基本</a>
<time class="recent-post-date">2024/01/29</time>
</li>
<li class="recent-post">
<a href="#" class="recent-post-link">レスポンシブデザインの重要性</a>
<time class="recent-post-date">2024/01/28</time>
</li>
<li class="recent-post">
<a href="#" class="recent-post-link">CSS Gridの使い方</a>
<time class="recent-post-date">2024/01/27</time>
</li>
</ul>
</section>
<section class="widget">
<h3 class="widget-title">カテゴリー</h3>
<ul class="categories">
<li><a href="#" class="category-link">HTML <span class="count">(5)</span></a></li>
<li><a href="#" class="category-link">CSS <span class="count">(8)</span></a></li>
<li><a href="#" class="category-link">JavaScript <span class="count">(3)</span></a></li>
<li><a href="#" class="category-link">デザイン <span class="count">(2)</span></a></li>
</ul>
</section>
</aside>
</div>
<footer class="site-footer">
<div class="footer-container">
<p class="copyright">© 2024 My Blog. All rights reserved.</p>
</div>
</footer>
</body>
</html>CSS(css/style.css)
/* ==========================================
リセットCSS
========================================== */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Helvetica Neue', Arial, 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif;
font-size: 16px;
line-height: 1.6;
color: #333;
background-color: #f5f5f5;
}
a {
color: #007bff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
img {
max-width: 100%;
height: auto;
}
ul {
list-style: none;
}
/* ==========================================
ヘッダー
========================================== */
.site-header {
background-color: #ffffff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
position: sticky;
top: 0;
z-index: 100;
}
.header-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
min-height: 60px;
}
.site-title {
font-size: 24px;
font-weight: bold;
color: #333;
}
.nav-list {
display: flex;
gap: 30px;
}
.nav-link {
color: #666;
font-weight: 500;
padding: 5px 0;
transition: color 0.3s ease;
}
.nav-link:hover {
color: #007bff;
text-decoration: none;
}
/* ==========================================
メインレイアウト(Flexbox)
========================================== */
.page-container {
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
display: flex;
gap: 40px;
align-items: flex-start; /* 上端揃え */
}
/* メインコンテンツ */
.main-content {
flex: 1; /* 残りスペースを占有 */
min-width: 0; /* Flexアイテムの縮小を許可 */
}
/* サイドバー */
.sidebar {
width: 300px;
flex-shrink: 0; /* 縮小しない */
}
/* ==========================================
記事
========================================== */
.article {
background-color: #ffffff;
border-radius: 8px;
padding: 30px;
margin-bottom: 30px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.article-header {
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 1px solid #eee;
}
.article-title {
font-size: 28px;
font-weight: bold;
margin-bottom: 10px;
color: #333;
}
.article-date {
color: #666;
font-size: 14px;
}
.article-content h3 {
font-size: 20px;
margin: 20px 0 10px;
color: #333;
}
.article-content ul {
list-style: disc inside;
margin: 15px 0;
padding-left: 20px;
}
.article-content p {
margin-bottom: 15px;
}
/* ==========================================
サイドバー
========================================== */
.widget {
background-color: #ffffff;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.widget-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 2px solid #007bff;
color: #333;
}
/* プロフィール */
.profile {
display: flex;
align-items: center;
gap: 15px;
}
.profile-image {
width: 60px;
height: 60px;
border-radius: 50%;
object-fit: cover;
flex-shrink: 0;
}
.profile-text {
font-size: 14px;
line-height: 1.5;
}
/* 最新記事 */
.recent-posts {
display: flex;
flex-direction: column;
gap: 12px;
}
.recent-post {
padding-bottom: 12px;
border-bottom: 1px solid #eee;
}
.recent-post:last-child {
border-bottom: none;
padding-bottom: 0;
}
.recent-post-link {
display: block;
font-weight: 500;
margin-bottom: 5px;
}
.recent-post-date {
font-size: 12px;
color: #999;
}
/* カテゴリー */
.categories {
display: flex;
flex-direction: column;
gap: 8px;
}
.category-link {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 12px;
background-color: #f8f9fa;
border-radius: 4px;
transition: background-color 0.3s ease;
}
.category-link:hover {
background-color: #e9ecef;
text-decoration: none;
}
.count {
font-size: 12px;
color: #666;
}
/* ==========================================
フッター
========================================== */
.site-footer {
background-color: #333;
color: #fff;
text-align: center;
padding: 20px 0;
margin-top: 50px;
}
.footer-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.copyright {
font-size: 14px;
}
/* ==========================================
レスポンシブデザイン
========================================== */
/* タブレット */
@media (max-width: 768px) {
.header-container {
flex-direction: column;
padding: 20px;
gap: 15px;
}
.nav-list {
gap: 20px;
}
.page-container {
flex-direction: column;
gap: 30px;
}
.sidebar {
width: 100%;
}
.article {
padding: 20px;
}
.article-title {
font-size: 24px;
}
}
/* モバイル */
@media (max-width: 480px) {
.header-container {
padding: 15px;
}
.site-title {
font-size: 20px;
}
.nav-list {
flex-wrap: wrap;
justify-content: center;
gap: 15px;
}
.page-container {
padding: 20px 15px;
}
.article {
padding: 15px;
}
.article-title {
font-size: 20px;
}
.profile {
flex-direction: column;
text-align: center;
}
.widget {
padding: 15px;
}
}
/* 横向きスマホ・小さなタブレット */
@media (max-width: 768px) and (orientation: landscape) {
.page-container {
flex-direction: row;
}
.sidebar {
width: 250px;
}
}レスポンシブデザインのポイント
ブレークポイントの設定
/* 一般的なブレークポイント */
@media (min-width: 576px) { /* Small devices (landscape phones) */ }
@media (min-width: 768px) { /* Medium devices (tablets) */ }
@media (min-width: 992px) { /* Large devices (desktops) */ }
@media (min-width: 1200px) { /* Extra large devices (large desktops) */ }
/* カスタムブレークポイント */
@media (max-width: 1023px) { /* タブレット以下 */ }
@media (max-width: 767px) { /* スマホ */ }
@media (max-width: 479px) { /* 小さなスマホ */ }Flexboxでレスポンシブ対応
.container {
display: flex;
flex-wrap: wrap; /* 狭い画面では折り返し */
}
.item {
flex: 1 1 300px; /* 最小幅300px、それ以上は均等分割 */
}
/* モバイルでは縦並び */
@media (max-width: 767px) {
.container {
flex-direction: column;
}
.item {
flex: none; /* 固定サイズに戻す */
}
}📝 まとめ・質疑応答(5分)
Flexboxの主要概念の確認
✅ チェックリスト
- display: flexの効果を理解した
- 主軸と交差軸の概念を理解した
- justify-contentとalign-itemsを使い分けられる
- flexプロパティで伸縮を制御できる
- レスポンシブデザインの重要性を理解した
次回予告:CSS Grid
次回学習する内容:
- CSS Gridの基本概念
- グリッドコンテナとグリッドアイテム
- 複雑なレイアウトの実現
- FlexboxとGridの使い分け
🏠 宿題
-
カードレイアウトの作成
.card-container { display: flex; flex-wrap: wrap; gap: 20px; } .card { flex: 1 1 300px; /* レスポンシブカード */ min-height: 200px; } -
ナビゲーションメニューの改良
- ハンバーガーメニューの実装(CSS のみ)
- スマホ版の縦並びレイアウト
-
発展課題:Holy Grail Layout
.page { display: flex; flex-direction: column; min-height: 100vh; } .content { display: flex; flex: 1; } .main { flex: 1; } .sidebar1 { width: 200px; order: -1; } .sidebar2 { width: 200px; }
📚 参考リソース
- CSS Tricks - A Complete Guide to Flexbox
- MDN - Flexbox
- Flexbox Froggy (ゲーム形式で学習)
- Can I Use - Flexbox
次回もお楽しみに! 📱
Last updated on