HTMLの<div>タグは、Webページのレイアウトやデザインを構築する「無色透明な箱」として機能する要素です。
本記事では、基本文法や他タグとの使い分けから、Flexboxによる横並び、余白の最適化、JS連携などを解説します。
HTMLの<div>タグとは?基本的な意味と役割
<div>タグとは、「デザインやレイアウトを作るための無色透明な箱」になります。
「div(ディブ)」は英語の「division(分割・区分)」の略称です。
海外のWeb開発においてもその役割は全く同じで、レイアウトを分断・整理するためのブロックとして認識されています。
タグ自体には、「見出し」や「段落」といった特別な意味(セマンティクス)は一切ありません。
しかし、複数のテキストや画像をこの「意味を持たない透明な箱」に入れてグループ化することで、CSSを使い横並びの配置や背景色によるカード型を実現します。
- ブロックレベル要素としての
divの役割 span・pタグとの違い(インラインとブロック)sectionやnavとの使い分け
HTMLの基本的な書き方や各タグの使い方を確かめたい人は「【初心者のHTML入門】基本構造の書き方とタグの使い方【タグ一覧表あり】」を一読ください。
ブロックレベル要素としてのdivの役割
<div>はHTMLにおいて「ブロックレベル要素」に分類されます。
ブロックレベル要素とは、ブラウザの画面上で「横幅いっぱいに広がり、前後に自動的に改行が入る箱」を指します。
複数のテキストや画像を<div>で囲んでグループ化し、CSSで背景色をつけたり、横に並べることでWebサイトのレイアウトを実現します。
レイアウトに慣れると陥るのが「とりあえず<div>で囲んでしまう」というミスです。
<div>の中に<div>があり、その中に<div>がある…という状態(通称:divスープ)になると、後からコードを見返した時に分からなくなります。
実務では、グループ化やデザインの指定が必要な箇所にだけ<div>を使うのがよいです。
この記事ではdivタグの使い方を解説します。
※各要素が独立しており、一つの「カード」として背景色や枠線をつけることができません。
この記事ではdivタグの使い方を解説します。
※divタグで囲んでグループ化したことで、全体に枠線や背景色を設定して「カード型デザイン」を作ることができました。
HTMLコード表示
<div class="hdiv1-wrapper">
<input type="radio" name="hdiv1-state" id="hdiv1-nogroup" class="hdiv1-radio" checked>
<input type="radio" name="hdiv1-state" id="hdiv1-group" class="hdiv1-radio">
<div class="hdiv1-controls">
<label for="hdiv1-nogroup" class="hdiv1-btn">❌ divなし (バラバラ)</label>
<label for="hdiv1-group" class="hdiv1-btn">⭕️ divで囲む (グループ化)</label>
</div>
<div class="hdiv1-demo-area">
<div class="hdiv1-box target-nogroup-hdiv1">
<div class="hdiv1-title">おすすめ記事</div>
<img src="https://placehold.co/150x100/eee/999?text=Image" alt="ダミー画像" class="hdiv1-img">
<p class="hdiv1-text">この記事ではdivタグの使い方を解説します。</p>
<button class="hdiv1-action">続きを読む</button>
<p class="hdiv1-note">※各要素が独立しており、一つの「カード」として背景色や枠線をつけることができません。</p>
</div>
<div class="hdiv1-box target-group-hdiv1">
<div class="hdiv1-card-wrapper">
<div class="hdiv1-title">おすすめ記事</div>
<img src="https://placehold.co/150x100/eee/999?text=Image" alt="ダミー画像" class="hdiv1-img">
<p class="hdiv1-text">この記事ではdivタグの使い方を解説します。</p>
<button class="hdiv1-action">続きを読む</button>
</div>
<p class="hdiv1-note hdiv1-note-ok">※divタグで囲んでグループ化したことで、全体に枠線や背景色を設定して「カード型デザイン」を作ることができました。</p>
</div>
</div>
</div>CSSコード表示
.hdiv1-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdiv1-radio {
display: none;
}
.hdiv1-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hdiv1-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hdiv1-nogroup:checked ~ .hdiv1-controls [for="hdiv1-nogroup"] {
background-color: #dc3545;
color: white;
}
#hdiv1-group:checked ~ .hdiv1-controls [for="hdiv1-group"] {
background-color: #198754;
color: white;
}
.hdiv1-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 30px 20px;
display: flex;
justify-content: center;
}
.hdiv1-box {
width: 100%;
max-width: 350px;
}
/* 中身の要素の基本スタイル(共通) */
.hdiv1-title {
font-size: 1.25rem;
margin: 0 0 10px 0;
color: #333;
font-weight: bold;
}
.hdiv1-img {
width: 100%;
max-width: 150px;
height: auto;
margin-bottom: 10px;
display: block;
}
.hdiv1-text {
font-size: 0.95rem;
margin: 0 0 15px 0;
color: #666;
line-height: 1.6;
}
.hdiv1-action {
background: #0d6efd;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
font-size: 13px;
font-weight: bold;
margin-bottom: 15px;
display: inline-block;
}
/* ★ divで囲んだ「カード」のスタイル(洗練されたデザイン) */
.target-group-hdiv1 {
background-color: #f1f3f5; /* カードの外側のグレー */
padding: 20px;
border-radius: 8px;
border: 1px solid #dee2e6;
}
.target-group-hdiv1 .hdiv1-card-wrapper {
background-color: #fff; /* カード本体の白 */
border-radius: 8px;
border: 1px solid #dee2e6;
padding: 20px;
box-shadow: 0 2px 5px rgba(0,0,0,0.05); /* わずかなシャドウ */
}
.target-group-hdiv1 .hdiv1-title {
margin-bottom: 15px;
}
.target-group-hdiv1 .hdiv1-img {
margin-bottom: 15px;
}
.target-group-hdiv1 .hdiv1-text {
margin-bottom: 20px;
}
/* NG用のリストスタイル(マージンを減らしてバラバラ感を強調) */
.target-nogroup-hdiv1 .hdiv1-title,
.target-nogroup-hdiv1 .hdiv1-img,
.target-nogroup-hdiv1 .hdiv1-text {
margin-bottom: 8px;
}
.target-nogroup-hdiv1 .hdiv1-action {
margin-bottom: 10px;
}
.hdiv1-note {
font-size: 13px;
color: #dc3545;
font-weight: bold;
line-height: 1.5;
margin: 0 0 10px 0;
padding-top: 15px;
border-top: 1px dashed #ccc;
}
.hdiv1-note-ok {
color: #198754;
}
.target-group-hdiv1 {
display: none;
}
#hdiv1-nogroup:checked ~ .hdiv1-demo-area .target-nogroup-hdiv1 {
display: block;
}
#hdiv1-group:checked ~ .hdiv1-demo-area .target-nogroup-hdiv1 {
display: none;
}
#hdiv1-group:checked ~ .hdiv1-demo-area .target-group-hdiv1 {
display: block;
}span・pタグとの違い(インラインとブロック)
迷うのが「いつ<div>を使い、いつ<span>や<p>を使うべきか?」という点です。
<p>タグとの違い<p>はParagraph(段落)の略で、「文章のひとまとまり」を表す意味を持ったブロックレベル要素です。
文章の集まりには<p>を使い、レイアウトの枠組みに<div>を使うのがルールです。<span>タグとの違い<span>も<div>と同様に「意味を持たない箱」ですが、<span>はインライン要素です。
文章中の一部の文字色を変えたい時など、「改行させず一部分だけを囲む」場合に使用します。
実務で見かけるHTMLの構文エラーが「<p>タグ(段落)の中に、<div>タグ(ブロック要素)を書いてしまう」というミスです。
HTMLの厳密なルールにおいて、<p>タグの中に別のブロックレベル要素を入れることは禁止されています。
ブラウザが強制的に<p>を閉じてしまい、意図しないレイアウト崩れを引き起こします。
「文章の一部を囲むときは必ず<span>を使う」と覚えておきましょう。
<div class=”red”>新鮮なトマト</div>
です。</p>
本日の特売品は
です。
※divは「横幅いっぱいに広がる箱」なので、前後に改行が入って文章が千切れてしまいます。
<span class=”red”>新鮮なトマト</span>
です。</p>
本日の特売品は新鮮なトマトです。
※spanは「文字に寄り添う箱(インライン)」なので、改行されずに一部分だけを装飾できます。
HTMLコード表示
<div class="hdiv2-wrapper">
<input type="radio" name="hdiv2-state" id="hdiv2-div" class="hdiv2-radio" checked>
<input type="radio" name="hdiv2-state" id="hdiv2-span" class="hdiv2-radio">
<div class="hdiv2-controls">
<label for="hdiv2-div" class="hdiv2-btn">❌ divで一部を囲む (改行される)</label>
<label for="hdiv2-span" class="hdiv2-btn">⭕️ spanで一部を囲む (改行されない)</label>
</div>
<div class="hdiv2-demo-area">
<div class="hdiv2-box target-div-hdiv2">
<div class="hdiv2-code">
<p>本日の特売品は<br>
<span class="hdiv2-highlight"><div class="red">新鮮なトマト</div></span><br>
です。</p>
</div>
<div class="hdiv2-render">
<p>本日の特売品は</p>
<div class="hdiv2-red-text">新鮮なトマト</div>
<p>です。</p>
</div>
<p class="hdiv2-note">※divは「横幅いっぱいに広がる箱」なので、前後に改行が入って文章が千切れてしまいます。</p>
</div>
<div class="hdiv2-box target-span-hdiv2">
<div class="hdiv2-code hdiv2-code-ok">
<p>本日の特売品は<br>
<span class="hdiv2-highlight"><span class="red">新鮮なトマト</span></span><br>
です。</p>
</div>
<div class="hdiv2-render">
<p>本日の特売品は<span class="hdiv2-red-text">新鮮なトマト</span>です。</p>
</div>
<p class="hdiv2-note hdiv2-note-ok">※spanは「文字に寄り添う箱(インライン)」なので、改行されずに一部分だけを装飾できます。</p>
</div>
</div>
</div>CSSコード表示
.hdiv2-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdiv2-radio {
display: none;
}
.hdiv2-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hdiv2-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hdiv2-div:checked ~ .hdiv2-controls [for="hdiv2-div"] {
background-color: #dc3545;
color: white;
}
#hdiv2-span:checked ~ .hdiv2-controls [for="hdiv2-span"] {
background-color: #198754;
color: white;
}
.hdiv2-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 30px 20px;
display: flex;
justify-content: center;
}
.hdiv2-box {
width: 100%;
max-width: 400px;
}
.hdiv2-code {
background-color: #f8d7da;
color: #842029;
padding: 15px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
border-left: 4px solid #dc3545;
margin-bottom: 15px;
line-height: 1.5;
}
.hdiv2-code-ok {
background-color: #d1e7dd;
color: #0f5132;
border-left: 4px solid #198754;
}
.hdiv2-highlight {
font-weight: bold;
text-decoration: underline;
}
.hdiv2-render {
background-color: #f1f3f5;
padding: 20px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
color: #333;
margin-bottom: 15px;
}
.hdiv2-render p {
margin: 0;
}
.hdiv2-red-text {
color: #dc3545;
font-weight: bold;
background-color: #ffe6e6;
padding: 2px 4px;
border-radius: 2px;
}
.hdiv2-note {
font-size: 13px;
color: #dc3545;
font-weight: bold;
line-height: 1.5;
margin: 0;
}
.hdiv2-note-ok {
color: #198754;
}
.target-span-hdiv2 {
display: none;
}
#hdiv2-div:checked ~ .hdiv2-demo-area .target-div-hdiv2 {
display: block;
}
#hdiv2-span:checked ~ .hdiv2-demo-area .target-div-hdiv2 {
display: none;
}
#hdiv2-span:checked ~ .hdiv2-demo-area .target-span-hdiv2 {
display: block;
}sectionやnavとの使い分け
ページ構造を示す「セマンティックタグ(意味を持つタグ)」が多数存在します。
実務では、これらと無意味な<div>を正しく使い分けることがSEO評価に直結します。
<section>との使い分け<section>は「見出し(h1〜h6)を伴う意味のあるコンテンツの区切り」に使用します。
対して<div>は、CSSでデザインを整える「意味のない外枠(ラッパー)」として使用します。<nav>との使い分け<nav>はサイト内のナビゲーションリンク(グローバルメニューなど)の集まりに使用します。<table>との使い分け
昔のWebサイトは、レイアウトを組む表組みタグである<table>が乱用されていました。
現在は、レイアウト目的に<div>を使い、純粋な「表データ」にのみ<table>を使用します。
中央寄せにするための外枠や背景色をつけるコンテナまで<section>を使ってしまうケースが多いです。
見出しが存在しない、あるいは文章構造として意味を持たない「ただの箱」が必要な場合は、<div>を使うのが検索エンジンにとっても正しいHTMLの書き方です。
<section class=”container”>
<!– 意味のあるコンテンツの塊 –>
<section class=”service-area”>
<h2>当社のサービス</h2>
<p>高品質なWeb制作を提供します。</p>
</section>
</section>
※見出しを伴わない単なるレイアウト用の外枠に「section」を使うのは意味論的に間違っています。
<div class=”container”>
<!– 見出しを伴う意味のあるコンテンツの塊 –>
<section class=”service-area”>
<h2>当社のサービス</h2>
<p>高品質なWeb制作を提供します。</p>
</section>
</div>
※デザイン・レイアウトのためだけの箱には、堂々と「div」を使うのが正解です。
HTMLコード表示
<div class="hdiv3-wrapper">
<input type="radio" name="hdiv3-state" id="hdiv3-bad" class="hdiv3-radio" checked>
<input type="radio" name="hdiv3-state" id="hdiv3-good" class="hdiv3-radio">
<div class="hdiv3-controls">
<label for="hdiv3-bad" class="hdiv3-btn">❌ sectionの乱用 (NG)</label>
<label for="hdiv3-good" class="hdiv3-btn">⭕️ 正しい使い分け (OK)</label>
</div>
<div class="hdiv3-demo-area">
<div class="hdiv3-box target-bad-hdiv3">
<div class="hdiv3-code">
<span class="hdiv3-comment"><!-- 中央寄せにするための外枠(見出しなし) --></span><br>
<span class="hdiv3-tag-error"><section class="container"></span><br>
<br>
<span class="hdiv3-comment"><!-- 意味のあるコンテンツの塊 --></span><br>
<section class="service-area"><br>
<h2>当社のサービス</h2><br>
<p>高品質なWeb制作を提供します。</p><br>
</section><br>
<br>
<span class="hdiv3-tag-error"></section></span>
</div>
<p class="hdiv3-note">※見出しを伴わない単なるレイアウト用の外枠に「section」を使うのは意味論的に間違っています。</p>
</div>
<div class="hdiv3-box target-good-hdiv3">
<div class="hdiv3-code hdiv3-code-ok">
<span class="hdiv3-comment"><!-- 中央寄せにするための外枠(意味を持たない箱) --></span><br>
<span class="hdiv3-tag-ok"><div class="container"></span><br>
<br>
<span class="hdiv3-comment"><!-- 見出しを伴う意味のあるコンテンツの塊 --></span><br>
<section class="service-area"><br>
<h2>当社のサービス</h2><br>
<p>高品質なWeb制作を提供します。</p><br>
</section><br>
<br>
<span class="hdiv3-tag-ok"></div></span>
</div>
<p class="hdiv3-note hdiv3-note-ok">※デザイン・レイアウトのためだけの箱には、堂々と「div」を使うのが正解です。</p>
</div>
</div>
</div>CSSコード表示
.hdiv3-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdiv3-radio {
display: none;
}
.hdiv3-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hdiv3-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hdiv3-bad:checked ~ .hdiv3-controls [for="hdiv3-bad"] {
background-color: #dc3545;
color: white;
}
#hdiv3-good:checked ~ .hdiv3-controls [for="hdiv3-good"] {
background-color: #198754;
color: white;
}
.hdiv3-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 30px 20px;
display: flex;
justify-content: center;
}
.hdiv3-box {
width: 100%;
max-width: 450px;
}
.hdiv3-code {
background-color: #282c34;
color: #abb2bf;
padding: 20px;
font-family: monospace;
font-size: 13px;
border-radius: 4px;
margin-bottom: 15px;
line-height: 1.6;
}
.hdiv3-comment {
color: #5c6370;
font-style: italic;
}
.hdiv3-tag-error {
color: #e06c75;
font-weight: bold;
background-color: rgba(224, 108, 117, 0.2);
padding: 2px 4px;
border-radius: 2px;
}
.hdiv3-tag-ok {
color: #98c379;
font-weight: bold;
background-color: rgba(152, 195, 121, 0.2);
padding: 2px 4px;
border-radius: 2px;
}
.hdiv3-note {
font-size: 13px;
color: #dc3545;
font-weight: bold;
line-height: 1.5;
margin: 0;
}
.hdiv3-note-ok {
color: #198754;
}
.target-good-hdiv3 {
display: none;
}
#hdiv3-bad:checked ~ .hdiv3-demo-area .target-bad-hdiv3 {
display: block;
}
#hdiv3-good:checked ~ .hdiv3-demo-area .target-bad-hdiv3 {
display: none;
}
#hdiv3-good:checked ~ .hdiv3-demo-area .target-good-hdiv3 {
display: block;
}divタグの基本文法(class・id・入れ子)
<div>タグは、単体では「無色透明な箱」に過ぎません。
この箱にデザインを適用したり、レイアウトを組んだりするには、箱に「名前(識別子)」をつける必要があります。
その役割を担うのがclass属性 とid属性です。
class属性・id属性での名前の付け方divタグの入れ子(ネスト)構造と注意点
class属性・id属性での名前の付け方
箱に名前をつける際、「class」と「id」にはルールの違いがあります。
- class属性
同じページ内で何度でも繰り返し使える名前。
(例:.card、.btnなど共通のデザインを適用したい場合に使用) - id属性
同じページ内で1度しか使えない固有の名前。
(例:#header、#footerなどページ内で唯一無二の要素やJavaScriptの処理の起点に使用)
また、classは半角スペースで区切ることで1つの<div>に複数の名前をつけられます。(例:<div class="btn btn-red">)
これにより、「基本のボタンスタイル」+「赤色にするスタイル」のように、CSSの部品を組み合わせて効率よくコーディングする手法が実現できます。
さらに、JavaScriptでデータを扱うための目印としてdata-*属性を付与するテクニックも使われます。(例:<div data-item-id="123">)
やりがちなミスが「CSS装飾をidで指定すること」です。
idはページ内に1つしか存在してはいけないため、あとから「デザイン別の場所でも使いたいな」と思った時に使い回すことができません。
また、CSSの優先順位(詳細度)が強くなり、あとから別スタイルで上書きできなくなるバグを生み出します。
「CSS装飾はclassで行い、idはページ内リンク(アンカー)やJavaScriptの取得用にのみ使う」というのがよいでしょう。
共通のデザイン
共通デザイン + ID
共通デザイン + 拡張カラー
【class属性】
「.box」という共通のクラス名をつけることで、3つの箱すべてに同じ枠線や余白を一括で適用しています。
HTMLコード表示
<div class="hdci1-wrapper">
<input type="radio" name="hdci1-state" id="hdci1-class" class="hdci1-radio" checked>
<input type="radio" name="hdci1-state" id="hdci1-id" class="hdci1-radio">
<input type="radio" name="hdci1-state" id="hdci1-multi" class="hdci1-radio">
<div class="hdci1-controls">
<label for="hdci1-class" class="hdci1-btn">class (共通装飾)</label>
<label for="hdci1-id" class="hdci1-btn">id (固有の目印)</label>
<label for="hdci1-multi" class="hdci1-btn">複数class (拡張)</label>
</div>
<div class="hdci1-demo-area">
<div class="hdci1-box-item target-class-active">
<div class="hdci1-code-label"><div class="box"></div>
<p>共通のデザイン</p>
</div>
<div class="hdci1-box-item target-id-active" id="hdci1-special-box">
<div class="hdci1-code-label"><div class="box" <span class="hdci1-hl-id">id="special"</span>></div>
<p>共通デザイン + ID</p>
</div>
<div class="hdci1-box-item hdci1-box-dark target-multi-active">
<div class="hdci1-code-label"><div class="box <span class="hdci1-hl-class">box-dark</span>"></div>
<p>共通デザイン + 拡張カラー</p>
</div>
</div>
<div class="hdci1-explanation">
<p id="desc-class" class="hdci1-desc">【class属性】<br>「.box」という共通のクラス名をつけることで、3つの箱すべてに同じ枠線や余白を一括で適用しています。</p>
<p id="desc-id" class="hdci1-desc" style="display:none;">【id属性】<br>「#special」はページ内に1つだけ存在できる固有の名前です。JSで特定したり、ページ内リンクの着地点として使われます。(※デザイン目的では使いません)</p>
<p id="desc-multi" class="hdci1-desc" style="display:none;">【複数class】<br>半角スペースを空けて「box-dark」というクラスを追加することで、基本デザインを保ったまま背景色だけを黒に変更(拡張)しています。</p>
</div>
</div>CSSコード表示
.hdci1-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdci1-radio {
display: none;
}
.hdci1-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hdci1-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hdci1-class:checked ~ .hdci1-controls [for="hdci1-class"] {
background-color: #0d6efd;
color: white;
}
#hdci1-id:checked ~ .hdci1-controls [for="hdci1-id"] {
background-color: #dc3545;
color: white;
}
#hdci1-multi:checked ~ .hdci1-controls [for="hdci1-multi"] {
background-color: #198754;
color: white;
}
.hdci1-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 20px;
display: flex;
flex-direction: column;
gap: 15px;
margin-bottom: 15px;
}
/* ★ 共通のclass(.box に相当) */
.hdci1-box-item {
border: 2px solid #0d6efd;
background-color: #e7f1ff;
padding: 15px;
border-radius: 6px;
text-align: center;
color: #0d6efd;
font-weight: bold;
transition: all 0.3s ease;
}
.hdci1-code-label {
font-family: monospace;
font-size: 13px;
color: #666;
margin-bottom: 5px;
}
/* ★ 複数class用の拡張(.box-dark に相当) */
.hdci1-box-dark {
background-color: #212529;
border-color: #212529;
color: #ffffff;
}
.hdci1-hl-id {
color: #dc3545;
font-weight: bold;
}
.hdci1-hl-class {
color: #198754;
font-weight: bold;
}
/* ラジオボタンによるハイライト表示 */
#hdci1-id:checked ~ .hdci1-demo-area .target-id-active {
box-shadow: 0 0 0 4px rgba(220,53,69,0.5);
transform: scale(1.02);
}
#hdci1-multi:checked ~ .hdci1-demo-area .target-multi-active {
box-shadow: 0 0 0 4px rgba(25,135,84,0.5);
transform: scale(1.02);
}
.hdci1-explanation {
background-color: #fff;
padding: 15px;
border: 1px solid #ccc;
border-radius: 4px;
}
.hdci1-desc {
margin: 0;
font-size: 14px;
line-height: 1.6;
color: #333;
}
/* 説明文の切り替え */
#hdci1-class:checked ~ .hdci1-explanation #desc-class {
display: block !important;
}
#hdci1-class:checked ~ .hdci1-explanation #desc-id,
#hdci1-class:checked ~ .hdci1-explanation #desc-multi {
display: none !important;
}
#hdci1-id:checked ~ .hdci1-explanation #desc-id {
display: block !important;
}
#hdci1-id:checked ~ .hdci1-explanation #desc-class,
#hdci1-id:checked ~ .hdci1-explanation #desc-multi {
display: none !important;
}
#hdci1-multi:checked ~ .hdci1-explanation #desc-multi {
display: block !important;
}
#hdci1-multi:checked ~ .hdci1-explanation #desc-class,
#hdci1-multi:checked ~ .hdci1-explanation #desc-id {
display: none !important;
}divタグの入れ子(ネスト)構造と注意点
Webサイトの複雑なレイアウトは、大きな箱の中に中くらいの箱を入れ、さらにその中に小さな箱を入れる…という「入れ子(ネスト)」構造によって作られます。
外側を囲むdivを「親要素」、中に入るdivを「子要素」と呼びます。
レイアウトに苦戦すると、「とりあえずdivで囲んで余白を調整しよう」と安易に考えてしまいがちです。
結果として、意味もなくdivが何重にも入れ子になる「divだらけ」の状態に陥ります。
可能な限り浅い(シンプルな)階層を保つのがよいです。
文章が入ります
※「divの中にdivの中にdiv…」と無駄な箱が多く、コードが非常に読みづらくなります(divスープ)。
文章が入ります
※親要素にpadding(内側の余白)や背景色を指定すれば、余計なdivを作らずに1つの階層でスッキリ収まります。
HTMLコード表示
<div class="hdin1-wrapper">
<input type="radio" name="hdin1-state" id="hdin1-bad" class="hdin1-radio" checked>
<input type="radio" name="hdin1-state" id="hdin1-good" class="hdin1-radio">
<div class="hdin1-controls">
<label for="hdin1-bad" class="hdin1-btn">❌ divスープ (階層が深すぎる)</label>
<label for="hdin1-good" class="hdin1-btn">⭕️ シンプルな構造 (最適)</label>
</div>
<div class="hdin1-demo-area">
<div class="hdin1-box target-bad-hdin1">
<div class="hdin1-code-visual">
<div class="hdin1-v-box level-1">
<span class="hdin1-v-label">外枠div</span>
<div class="hdin1-v-box level-2">
<span class="hdin1-v-label">余白用div</span>
<div class="hdin1-v-box level-3">
<span class="hdin1-v-label">背景用div</span>
<div class="hdin1-v-box level-4">
<span class="hdin1-v-label">テキスト配置用div</span>
<p class="hdin1-v-content">文章が入ります</p>
</div>
</div>
</div>
</div>
</div>
<p class="hdin1-note">※「divの中にdivの中にdiv…」と無駄な箱が多く、コードが非常に読みづらくなります(divスープ)。</p>
</div>
<div class="hdin1-box target-good-hdin1">
<div class="hdin1-code-visual">
<div class="hdin1-v-box level-ok">
<span class="hdin1-v-label">カード全体の親div(余白・背景をここで一括指定)</span>
<p class="hdin1-v-content hdin1-v-content-ok">文章が入ります</p>
</div>
</div>
<p class="hdin1-note hdin1-note-ok">※親要素にpadding(内側の余白)や背景色を指定すれば、余計なdivを作らずに1つの階層でスッキリ収まります。</p>
</div>
</div>
</div>CSSコード表示
.hdin1-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdin1-radio {
display: none;
}
.hdin1-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hdin1-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hdin1-bad:checked ~ .hdin1-controls [for="hdin1-bad"] {
background-color: #dc3545;
color: white;
}
#hdin1-good:checked ~ .hdin1-controls [for="hdin1-good"] {
background-color: #198754;
color: white;
}
.hdin1-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 30px 20px;
display: flex;
justify-content: center;
}
.hdin1-box {
width: 100%;
max-width: 450px;
}
/* 入れ子の可視化用スタイル */
.hdin1-code-visual {
background-color: #fff;
padding: 15px;
border-radius: 8px;
margin-bottom: 15px;
}
.hdin1-v-box {
border: 2px solid;
padding: 15px;
margin-bottom: 5px;
border-radius: 4px;
}
.hdin1-v-label {
display: block;
font-size: 12px;
font-weight: bold;
margin-bottom: 10px;
}
/* 階層ごとの色分け(NG例) */
.level-1 {
border-color: #0d6efd;
background-color: rgba(13,110,253,0.05);
}
.level-1 > .hdin1-v-label { color: #0d6efd; }
.level-2 {
border-color: #6610f2;
background-color: rgba(102,16,242,0.05);
}
.level-2 > .hdin1-v-label { color: #6610f2; }
.level-3 {
border-color: #fd7e14;
background-color: rgba(253,126,20,0.05);
}
.level-3 > .hdin1-v-label { color: #fd7e14; }
.level-4 {
border-color: #dc3545;
background-color: rgba(220,53,69,0.05);
}
.level-4 > .hdin1-v-label { color: #dc3545; }
/* OK例のスタイル */
.level-ok {
border-color: #198754;
background-color: rgba(25,135,84,0.05);
padding: 30px; /* 余白をここでまとめて取る */
}
.level-ok > .hdin1-v-label { color: #198754; }
.hdin1-v-content {
background-color: #e9ecef;
padding: 15px;
text-align: center;
margin: 0;
font-size: 14px;
color: #333;
}
.hdin1-v-content-ok {
background-color: #d1e7dd; /* 中身の背景色もスマートに */
}
.hdin1-note {
font-size: 13px;
color: #dc3545;
font-weight: bold;
line-height: 1.5;
margin: 0;
padding-top: 15px;
border-top: 1px dashed #ccc;
}
.hdin1-note-ok {
color: #198754;
}
/* 切り替え */
.target-good-hdin1 {
display: none;
}
#hdin1-bad:checked ~ .hdin1-demo-area .target-bad-hdin1 {
display: block;
}
#hdin1-good:checked ~ .hdin1-demo-area .target-bad-hdin1 {
display: none;
}
#hdin1-good:checked ~ .hdin1-demo-area .target-good-hdin1 {
display: block;
}divを横並び・分割するレイアウト手法
<div>タグは「ブロックレベル要素」であるため、HTMLに記述すると縦に積み重なります。
しかし、実際のWebサイトでは、画像とテキストを左右に並べたり、記事カードを3つ並べたりといったレイアウトが求められます。
- Flexboxを使った2列・3列の横並び
- CSS Gridを使ったレイアウト分割
floatやinline-blockでの横並びと間隔調整
Flexboxを使った2列・3列の横並び
現在、要素を横に並べる標準的な手法が「Flexbox(フレックスボックス)」です。
横に並べたい子要素を囲む「親の<div>」に対して、CSSでdisplay: flex;を指定するだけです。
これだけで、中の子要素が自動的に左から右へと横並びになります。
子要素の幅を50%や33.3%と指定することで、2列や3列のレイアウトを作れます。
Flexboxを学び始めた際、「並べたい要素(子要素)自身にdisplay: flex;を書いてしまい、横並びにならない。」といったミスがあります。
Flexboxは「親要素」にかけるものだと覚えておきましょう。
【デフォルト】
divはブロック要素なので、上から下へと縦に積み重なります。
HTMLコード表示
<div class="hlay1-wrapper">
<input type="radio" name="hlay1-state" id="hlay1-block" class="hlay1-radio" checked>
<input type="radio" name="hlay1-state" id="hlay1-flex" class="hlay1-radio">
<input type="radio" name="hlay1-state" id="hlay1-wrap" class="hlay1-radio">
<div class="hlay1-controls">
<label for="hlay1-block" class="hlay1-btn">❌ デフォルト (縦積み)</label>
<label for="hlay1-flex" class="hlay1-btn">⭕️ display: flex (横並び)</label>
<label for="hlay1-wrap" class="hlay1-btn">✨ flex-wrap: wrap (折り返し)</label>
</div>
<div class="hlay1-demo-area">
<div class="hlay1-parent target-parent-hlay1">
<div class="hlay1-child">要素1 (33.3%)</div>
<div class="hlay1-child">要素2 (33.3%)</div>
<div class="hlay1-child">要素3 (33.3%)</div>
<div class="hlay1-child">要素4 (33.3%)</div>
</div>
</div>
<div class="hlay1-explanation">
<p id="desc-block" class="hlay1-desc">【デフォルト】<br>divはブロック要素なので、上から下へと縦に積み重なります。</p>
<p id="desc-flex" class="hlay1-desc" style="display:none;">【display: flex;】<br>親要素に指定すると横並びになりますが、要素が4つあるため、はみ出さないように無理やり幅が圧縮されて潰れています。</p>
<p id="desc-wrap" class="hlay1-desc" style="display:none;">【+ flex-wrap: wrap;】<br>親要素の幅を超えた分は自動的に下の行へ折り返されるようになり、綺麗な3列(余った1つは下)のグリッドが完成します。</p>
</div>
</div>CSSコード表示
.hlay1-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hlay1-radio {
display: none;
}
.hlay1-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hlay1-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hlay1-block:checked ~ .hlay1-controls [for="hlay1-block"] {
background-color: #dc3545;
color: white;
}
#hlay1-flex:checked ~ .hlay1-controls [for="hlay1-flex"] {
background-color: #0d6efd;
color: white;
}
#hlay1-wrap:checked ~ .hlay1-controls [for="hlay1-wrap"] {
background-color: #198754;
color: white;
}
.hlay1-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 20px;
margin-bottom: 15px;
}
/* 親要素のベーススタイル */
.hlay1-parent {
background-color: #e9ecef;
padding: 10px;
border-radius: 4px;
transition: all 0.3s ease;
}
/* 子要素のスタイル(幅を33.3%から隙間分引いたサイズに設定) */
.hlay1-child {
background-color: #0d6efd;
color: white;
padding: 20px 10px;
border-radius: 4px;
text-align: center;
font-weight: bold;
font-size: 14px;
box-sizing: border-box;
}
/* ラジオボタンに応じた親要素のレイアウト変更 */
#hlay1-block:checked ~ .hlay1-demo-area .target-parent-hlay1 {
display: block; /* デフォルト */
}
#hlay1-block:checked ~ .hlay1-demo-area .hlay1-child {
margin-bottom: 10px;
}
#hlay1-flex:checked ~ .hlay1-demo-area .target-parent-hlay1 {
display: flex; /* 横並びの魔法 */
gap: 10px; /* 要素間の隙間 */
}
#hlay1-flex:checked ~ .hlay1-demo-area .hlay1-child {
width: calc(33.333% - 6.66px); /* 3列分の幅 */
}
#hlay1-wrap:checked ~ .hlay1-demo-area .target-parent-hlay1 {
display: flex;
gap: 10px;
flex-wrap: wrap; /* はみ出したら折り返す魔法 */
}
#hlay1-wrap:checked ~ .hlay1-demo-area .hlay1-child {
width: calc(33.333% - 6.66px);
}
.hlay1-explanation {
background-color: #fff;
padding: 15px;
border: 1px solid #ccc;
border-radius: 4px;
}
.hlay1-desc {
margin: 0;
font-size: 14px;
line-height: 1.6;
color: #333;
}
#hlay1-block:checked ~ .hlay1-explanation #desc-block {
display: block !important;
}
#hlay1-block:checked ~ .hlay1-explanation #desc-flex,
#hlay1-block:checked ~ .hlay1-explanation #desc-wrap {
display: none !important;
}
#hlay1-flex:checked ~ .hlay1-explanation #desc-flex {
display: block !important;
}
#hlay1-flex:checked ~ .hlay1-explanation #desc-block,
#hlay1-flex:checked ~ .hlay1-explanation #desc-wrap {
display: none !important;
}
#hlay1-wrap:checked ~ .hlay1-explanation #desc-wrap {
display: block !important;
}
#hlay1-wrap:checked ~ .hlay1-explanation #desc-block,
#hlay1-wrap:checked ~ .hlay1-explanation #desc-flex {
display: none !important;
}displayプロパティの使い方を詳しく知りたい人は「【html&css】displayの種類は?flexやinline-blockの違い」を一読ください。
CSS Gridを使ったレイアウト分割
Flexboxが「1次元(横一列、または縦一列)」を得意とするのに対し、CSS Gridは「2次元(縦横のマス目)」のレイアウトを組むのに特化した手法です。
例えば、親要素を半分に分割して左右に配置したい場合、Gridを使うとgrid-template-columns: 1fr 1fr;という直感的なコードで分割レイアウトが完成します。
ただし、Gridを覚えると単純な横並び(ナビゲーションメニューなど)にまでGridを使ってしまうことがあります。
Gridはマス目を定義するため、中身のテキストの長さに応じて柔軟に幅を変えるレイアウトには不向きです。
「中身に合わせて幅が可変する並びはFlexbox」「画面全体をマス目で分割するレイアウト(写真ギャラリーなど)は Grid」という使い分けがよいです。
HTMLコード表示
<div class="hlay2-wrapper">
<input type="radio" name="hlay2-state" id="hlay2-2col" class="hlay2-radio" checked>
<input type="radio" name="hlay2-state" id="hlay2-3col" class="hlay2-radio">
<div class="hlay2-controls">
<label for="hlay2-2col" class="hlay2-btn">Gridで2分割 (1fr 1fr)</label>
<label for="hlay2-3col" class="hlay2-btn">Gridで3分割 (1fr 1fr 1fr)</label>
</div>
<div class="hlay2-demo-area">
<div class="hlay2-parent target-grid-hlay2">
<div class="hlay2-child hlay2-color-1">コンテンツ A</div>
<div class="hlay2-child hlay2-color-2">コンテンツ B</div>
<div class="hlay2-child hlay2-color-3 target-child-3">コンテンツ C</div>
</div>
</div>
</div>CSSコード表示
.hlay2-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hlay2-radio {
display: none;
}
.hlay2-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hlay2-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hlay2-2col:checked ~ .hlay2-controls [for="hlay2-2col"] {
background-color: #6f42c1;
color: white;
}
#hlay2-3col:checked ~ .hlay2-controls [for="hlay2-3col"] {
background-color: #0dcaf0;
color: #000;
}
.hlay2-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 20px;
}
.hlay2-parent {
display: grid; /* Gridレイアウトを有効化 */
gap: 15px; /* マス目同士の隙間を15pxに設定 */
background-color: #e9ecef;
padding: 15px;
border-radius: 4px;
transition: all 0.3s ease;
}
.hlay2-child {
color: white;
padding: 30px 10px;
border-radius: 4px;
text-align: center;
font-weight: bold;
font-size: 16px;
}
.hlay2-color-1 {
background-color: #6f42c1;
}
.hlay2-color-2 {
background-color: #20c997;
}
.hlay2-color-3 {
background-color: #fd7e14;
}
/* 2分割のスタイル */
#hlay2-2col:checked ~ .hlay2-demo-area .target-grid-hlay2 {
grid-template-columns: 1fr 1fr; /* 1:1の比率で2つに分割 */
}
#hlay2-2col:checked ~ .hlay2-demo-area .target-child-3 {
display: none; /* 2分割時は3つ目を非表示 */
}
/* 3分割のスタイル */
#hlay2-3col:checked ~ .hlay2-demo-area .target-grid-hlay2 {
grid-template-columns: 1fr 1fr 1fr; /* 1:1:1の比率で3つに分割 */
}
#hlay2-3col:checked ~ .hlay2-demo-area .target-child-3 {
display: block;
}floatやinline-blockでの横並びと間隔調整
古い横並び手法であるfloatとdisplay: inline-block;があります。
現在これらの手法でレイアウトを組むことは非推奨ですが、古いWebサイトの改修案件などで遭遇するため、知識として知っておく必要があります。
floatを使って要素を横並びにすると、親要素が「子要素の高さを見失い、背景色が消えて後続のレイアウトが崩壊する」という仕様があります。
これを防ぐために、擬似要素を使って高さを取り戻す「clearfix(クリアフィックス)」というCSSを親に書くのが常識でした。
一方、inline-blockを使えば高さを失うことはありませんが、HTMLタグ同士の「改行」を半角スペースとして認識し、横並びの要素間に「謎の隙間」が空いてしまいます。
これを消すために、親要素の文字サイズをfont-size: 0;にするなどトリッキーな技が必要でした。
ちなみに、「どうしてもCSSを使わずに横並びにしたい」という特殊な環境では、<div>ではなく<table>タグを使って横並びにする「テーブルレイアウト」という手法が使われることがあります。
※幅を50%ずつに指定しているのに、改行による「謎の隙間」のせいで100%を超えてしまい、横並びにならず落ちてしまいます。
HTMLコード表示
<div class="hlay3-wrapper">
<input type="radio" name="hlay3-state" id="hlay3-bad" class="hlay3-radio" checked>
<input type="radio" name="hlay3-state" id="hlay3-good" class="hlay3-radio">
<div class="hlay3-controls">
<label for="hlay3-bad" class="hlay3-btn">❌ inline-block (謎の隙間)</label>
<label for="hlay3-good" class="hlay3-btn">⭕️ font-size: 0; で隙間を消去</label>
</div>
<div class="hlay3-demo-area">
<div class="hlay3-parent target-parent-hlay3">
<div class="hlay3-child">左 (50%)</div>
<div class="hlay3-child">右 (50%)</div>
</div>
<p class="hlay3-note" id="note-bad">※幅を50%ずつに指定しているのに、改行による「謎の隙間」のせいで100%を超えてしまい、横並びにならず落ちてしまいます。</p>
<p class="hlay3-note hlay3-note-ok" id="note-good" style="display:none;">※親要素の文字サイズを0にして隙間を消し、子要素で文字サイズを戻すという力技で、無理やり50%ずつの横並びを実現しています。</p>
</div>
</div>CSSコード表示
.hlay3-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hlay3-radio {
display: none;
}
.hlay3-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hlay3-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hlay3-bad:checked ~ .hlay3-controls [for="hlay3-bad"] {
background-color: #dc3545;
color: white;
}
#hlay3-good:checked ~ .hlay3-controls [for="hlay3-good"] {
background-color: #198754;
color: white;
}
.hlay3-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 20px;
}
.hlay3-parent {
background-color: #e9ecef;
padding: 10px;
border-radius: 4px;
}
.hlay3-child {
display: inline-block; /* 横並びにする古い手法 */
width: 50%; /* ぴったり半分にしたい */
background-color: #fd7e14;
color: white;
padding: 15px 0;
text-align: center;
font-weight: bold;
font-size: 16px;
box-sizing: border-box;
border: 2px solid #fff;
}
/* NG時の状態(改行による隙間がある状態) */
#hlay3-bad:checked ~ .hlay3-demo-area .target-parent-hlay3 {
/* 親要素に特別な処理をしない */
}
/* OK時の状態(隙間をハックで消した状態) */
#hlay3-good:checked ~ .hlay3-demo-area .target-parent-hlay3 {
font-size: 0; /* 謎の隙間(スペース)の文字サイズを0にして消し去る魔法 */
}
#hlay3-good:checked ~ .hlay3-demo-area .hlay3-child {
font-size: 16px; /* 子要素で文字サイズを復元する */
}
.hlay3-note {
font-size: 13px;
color: #dc3545;
font-weight: bold;
line-height: 1.5;
margin: 15px 0 0 0;
padding-top: 15px;
border-top: 1px dashed #ccc;
}
.hlay3-note-ok {
color: #198754;
}
#hlay3-bad:checked ~ .hlay3-demo-area #note-bad {
display: block;
}
#hlay3-bad:checked ~ .hlay3-demo-area #note-good {
display: none;
}
#hlay3-good:checked ~ .hlay3-demo-area #note-bad {
display: none;
}
#hlay3-good:checked ~ .hlay3-demo-area #note-good {
display: block;
}divの配置調整(中央寄せ・右寄せ・重ねる)
Webデザインにおいて、<div>タグを思い通りの場所に配置することは、レイアウトの基本です。
しかし、「中央に寄せたなのになぜか左に寄ったまま」「右下に配置したいのに上手くいかない」といった配置のトラブルは、初心者が時間を溶かしやすいポイントです。
ここでは、要素を中央や左右下へ寄せる手法と要素同士を重ねるpositionプロパティの使い方などを解説します。
<div>や中の要素を中央寄せにする- 左寄せ・右寄せ・下寄せの配置
positionを使った絶対配置(要素を重ねる)
<div>や中の要素を中央寄せにする
<div>を中央に配置しようとした際、理解すべきは「中身のテキストを中央にしたいのか?」それとも「<div>という箱を画面中央にしたいのか?」の違いです。
- 中身のテキストを中央にする
text-align: center;を指定します。 <div>の箱自体を中央にする
箱に横幅(width)を指定した上で、margin: 0 auto;を指定します。
左右の余白(margin)をブラウザに自動計算(auto)させ中央配置します。- 上下左右の真ん中に配置する
親要素にFlexbox(display: flex; justify-content: center; align-items: center;)を指定するのが主流です。
「margin: 0 auto;を書いたのに箱が中央に行かない。」となるのがよくあるミスです。
原因は「<div>に幅(width)が指定されていないから」です。
ブロックレベル要素である<div>は、デフォルトで横幅いっぱいに広がる(width: 100%)性質があります。
幅がいっぱいなので、左右に余白(auto)を割り当てる余裕がなく、結果として何も変化しないように見えます。
width: 300px;やwidth: 50%;などセットで指定しましょう。
(※widthの指定が必須)
完全な中央配置
HTMLコード表示
<div class="hpos1-wrapper">
<input type="radio" name="hpos1-state" id="hpos1-text" class="hpos1-radio" checked>
<input type="radio" name="hpos1-state" id="hpos1-box" class="hpos1-radio">
<input type="radio" name="hpos1-state" id="hpos1-flex" class="hpos1-radio">
<div class="hpos1-controls">
<label for="hpos1-text" class="hpos1-btn">テキストの中央寄せ</label>
<label for="hpos1-box" class="hpos1-btn">箱自体の中央寄せ (margin)</label>
<label for="hpos1-flex" class="hpos1-btn">上下左右のど真ん中 (Flexbox)</label>
</div>
<div class="hpos1-demo-area">
<div class="hpos1-parent target-text-hpos1">
<div class="hpos1-child">
text-align: center;
</div>
</div>
<div class="hpos1-parent target-box-hpos1">
<div class="hpos1-child hpos1-has-width">
margin: 0 auto;<br>(※widthの指定が必須)
</div>
</div>
<div class="hpos1-parent target-flex-hpos1">
<div class="hpos1-child hpos1-has-width">
Flexboxで<br>完全な中央配置
</div>
</div>
</div>
</div>CSSコード表示
.hpos1-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hpos1-radio {
display: none;
}
.hpos1-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hpos1-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hpos1-text:checked ~ .hpos1-controls [for="hpos1-text"] {
background-color: #0d6efd;
color: white;
}
#hpos1-box:checked ~ .hpos1-controls [for="hpos1-box"] {
background-color: #198754;
color: white;
}
#hpos1-flex:checked ~ .hpos1-controls [for="hpos1-flex"] {
background-color: #6f42c1;
color: white;
}
.hpos1-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 20px;
}
.hpos1-parent {
background-color: #e9ecef;
border-radius: 4px;
height: 200px; /* 高さを設けて上下中央寄せをわかりやすくする */
padding: 10px;
box-sizing: border-box;
display: none; /* 初期は非表示 */
}
.hpos1-child {
background-color: #0d6efd;
color: white;
padding: 20px;
border-radius: 4px;
font-weight: bold;
font-size: 14px;
box-sizing: border-box;
}
/* 1. テキストの中央寄せ */
#hpos1-text:checked ~ .hpos1-demo-area .target-text-hpos1 {
display: block;
}
#hpos1-text:checked ~ .hpos1-demo-area .target-text-hpos1 .hpos1-child {
text-align: center; /* 中身の文字だけが中央に行く */
}
/* 2. 箱自体の中央寄せ */
#hpos1-box:checked ~ .hpos1-demo-area .target-box-hpos1 {
display: block;
}
.hpos1-has-width {
width: 250px; /* 箱を中央に寄せるための必須条件 */
text-align: center;
}
#hpos1-box:checked ~ .hpos1-demo-area .target-box-hpos1 .hpos1-child {
background-color: #198754;
margin: 0 auto; /* 箱自体を左右の中央に寄せる */
}
/* 3. 上下左右のど真ん中(Flexbox) */
#hpos1-flex:checked ~ .hpos1-demo-area .target-flex-hpos1 {
display: flex; /* Flexboxを有効化 */
justify-content: center; /* 左右の中央寄せ */
align-items: center; /* 上下の中央寄せ */
}
#hpos1-flex:checked ~ .hpos1-demo-area .target-flex-hpos1 .hpos1-child {
background-color: #6f42c1;
}padding(内側の余白)やmargin(外側の余白)の使い方を知りたい人は「【html&css】paddingとmarginの違いは?上下左右の余白と順番」を一読ください。
左寄せ・右寄せ・下寄せの配置
ボタンやアイコンなど右側に配置したり、カード下部に固定したりするケースも発生します。
左寄せはHTMLのデフォルトの挙動ですが、それ以外はCSSでの制御が必要です。
- 右寄せ:親要素に
justify-content: flex-end;を指定する。 - 下寄せ:親要素に
align-items: flex-end;を指定する。 - 特定の要素だけを右に押す:押したい要素に
margin-left: auto;を指定する。
HTMLコード表示
<div class="hpos2-wrapper">
<input type="radio" name="hpos2-state" id="hpos2-right" class="hpos2-radio" checked>
<input type="radio" name="hpos2-state" id="hpos2-bottom" class="hpos2-radio">
<input type="radio" name="hpos2-state" id="hpos2-push" class="hpos2-radio">
<div class="hpos2-controls">
<label for="hpos2-right" class="hpos2-btn">右寄せ</label>
<label for="hpos2-bottom" class="hpos2-btn">下寄せ</label>
<label for="hpos2-push" class="hpos2-btn">一部だけ右に押しやる</label>
</div>
<div class="hpos2-demo-area">
<div class="hpos2-parent target-right-hpos2">
<div class="hpos2-child">要素</div>
</div>
<div class="hpos2-parent target-bottom-hpos2">
<div class="hpos2-child hpos2-color-2">要素</div>
</div>
<div class="hpos2-parent target-push-hpos2">
<div class="hpos2-child hpos2-color-3">左の要素</div>
<div class="hpos2-child hpos2-color-3 hpos2-push-item">右に押しやられた要素</div>
</div>
</div>
</div>CSSコード表示
.hpos2-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hpos2-radio {
display: none;
}
.hpos2-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hpos2-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hpos2-right:checked ~ .hpos2-controls [for="hpos2-right"] {
background-color: #0d6efd;
color: white;
}
#hpos2-bottom:checked ~ .hpos2-controls [for="hpos2-bottom"] {
background-color: #198754;
color: white;
}
#hpos2-push:checked ~ .hpos2-controls [for="hpos2-push"] {
background-color: #fd7e14;
color: white;
}
.hpos2-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 20px;
}
.hpos2-parent {
background-color: #e9ecef;
border-radius: 4px;
height: 150px;
padding: 15px;
box-sizing: border-box;
display: none;
}
.hpos2-child {
background-color: #0d6efd;
color: white;
padding: 10px 20px;
border-radius: 4px;
font-weight: bold;
font-size: 14px;
}
.hpos2-color-2 {
background-color: #198754;
}
.hpos2-color-3 {
background-color: #fd7e14;
}
/* 右寄せ:justify-content を使用 */
#hpos2-right:checked ~ .hpos2-demo-area .target-right-hpos2 {
display: flex;
justify-content: flex-end; /* 横方向の右端へ */
}
/* 下寄せ:align-items を使用 */
#hpos2-bottom:checked ~ .hpos2-demo-area .target-bottom-hpos2 {
display: flex;
justify-content: center;
align-items: flex-end; /* 縦方向の下端へ */
}
/* 一部だけ右寄せ:margin-left: auto; を使用 */
#hpos2-push:checked ~ .hpos2-demo-area .target-push-hpos2 {
display: flex;
align-items: center;
}
.hpos2-push-item {
margin-left: auto; /* この要素の左側の余白を最大化し、右へ押しやる */
}positionを使った絶対配置(要素を重ねる)
「画像の上に『NEW!』ラベルの<div>を重ねる」「背景の上にテキストが入った箱を重ねる」といった、要素同士をZ軸で重ねるレイアウトには、positionプロパティを使用します。
重ねるルールは以下の2ステップです。
- 基準となる親の箱に
position: relative;を指定する。 - 重ねたい子要素に
position: absolute;を指定し、top、bottom、left、rightで位置を決める。
重なりの順序は、z-indexというプロパティの数値の大きさで制御します。
※「relativeなし」を選択すると、NEW!バッジが親の枠組みを無視して、このデモエリア(または画面)の右上に飛んでいってしまいます。
HTMLコード表示
<div class="hpos3-wrapper">
<input type="radio" name="hpos3-state" id="hpos3-good" class="hpos3-radio" checked>
<input type="radio" name="hpos3-state" id="hpos3-bad" class="hpos3-radio">
<div class="hpos3-controls">
<label for="hpos3-good" class="hpos3-btn">⭕️ 親に relative あり (安全)</label>
<label for="hpos3-bad" class="hpos3-btn">❌ 親に relative なし (飛んでいく)</label>
</div>
<div class="hpos3-demo-area">
<div class="hpos3-parent hpos3-has-relative target-good-hpos3">
<div class="hpos3-base-content">
画像などの基準となるコンテンツ
</div>
<div class="hpos3-badge">NEW!</div>
</div>
<div class="hpos3-parent target-bad-hpos3">
<div class="hpos3-base-content">
画像などの基準となるコンテンツ
</div>
<div class="hpos3-badge hpos3-badge-bad">NEW!</div>
</div>
</div>
<p class="hpos3-note">※「relativeなし」を選択すると、NEW!バッジが親の枠組みを無視して、このデモエリア(または画面)の右上に飛んでいってしまいます。</p>
</div>
CSSコード表示
.hpos3-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
position: relative; /* NG例のバッジが画面外に完全に消えないようにデモ全体を基準化 */
}
.hpos3-radio {
display: none;
}
.hpos3-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hpos3-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hpos3-good:checked ~ .hpos3-controls [for="hpos3-good"] {
background-color: #198754;
color: white;
}
#hpos3-bad:checked ~ .hpos3-controls [for="hpos3-bad"] {
background-color: #dc3545;
color: white;
}
.hpos3-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 40px 20px;
display: flex;
justify-content: center;
min-height: 200px;
}
/* 親要素のベース */
.hpos3-parent {
background-color: #e9ecef;
width: 250px;
height: 150px;
border: 2px solid #ccc;
border-radius: 4px;
display: none;
/* positionの指定は後述 */
}
.hpos3-base-content {
padding: 20px;
color: #666;
text-align: center;
font-size: 14px;
height: 100%;
box-sizing: border-box;
display: flex;
align-items: center;
}
/* 重ねる要素(バッジ) */
.hpos3-badge {
position: absolute; /* 絶対配置 */
top: -15px; /* 上に少しはみ出させる */
right: -15px; /* 右に少しはみ出させる */
background-color: #dc3545;
color: white;
padding: 8px 15px;
border-radius: 20px;
font-weight: bold;
font-size: 14px;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
z-index: 10; /* 手前に持ってくる */
}
/* ⭕️ OK時:親に relative を指定 */
#hpos3-good:checked ~ .hpos3-demo-area .target-good-hpos3 {
display: block;
}
.hpos3-has-relative {
position: relative; /* 基準点 */
}
/* ❌ NG時:親に relative なし */
#hpos3-bad:checked ~ .hpos3-demo-area .target-bad-hpos3 {
display: block;
}
/* NG時のバッジは、このデモエリアの親(.hpos3-wrapper)を基準にして飛んでいく */
.hpos3-badge-bad {
background-color: #6c757d;
}
.hpos3-note {
font-size: 13px;
color: #dc3545;
font-weight: bold;
line-height: 1.5;
margin: 15px 0 0 0;
text-align: center;
}<div>の幅・高さ・余白の指定
<div>タグを使ってレイアウトを組むには、箱の大きさと箱同士の距離や箱の内側の余白を正しくコントロールする必要があります。
デザイン崩れの原因の多くは「高さの固定によるはみ出し」や「マージンとパディングの混同」にあります。
ここでは、大きさの指定方法とレスポンシブデザイン(スマホ対応)の基本になる余白の使い分けにを解説します。
- 幅(
width)と高さ(height)の固定・自動調整 - 高さを100%や画面いっぱいに広げる
- マージンとパディングで適切な余白を作る
幅(width)と高さ(height)の詳細な設定方法を知りたい人は「【html&css】width(横幅)とheight(高さ)の指定とボックスモデル」を一読ください。
また、padding(内側の余白)やmargin(外側の余白)の使い方を詳しく知りたい人は「【html&css】paddingとmarginの違いは?上下左右の余白と順番」を一読ください。
幅(width)と高さ(height)の固定・自動調整
<div>の横幅と高さを決める際、width: 500px;やheight: 300px;のようにピクセル(px)で固定してしまいがちです。
PCの画面サイズだけを見て高さを固定すると、スマホの画面で見た時に文字が折り返されて行数が増え、指定した高さを超えて文字が箱からはみ出すという表示崩れが発生します。
実務では、横幅はwidth: 100%;やmax-width: 800px;のように指定し、高さに関しては「あえて何も指定しないheight: auto;」のがよいです。
高さをautoにしておけば、中のテキストの量に応じて箱が自動的に縦に伸びるため、文字がはみ出すことはありません。
テキスト量が増えたり、スマホの狭い画面で折り返されたりして行数が増えると、固定された100pxの高さを超えてしまい、このように箱から文字が盛大にはみ出してレイアウトが崩壊します。
高さをauto(デフォルト)にしておけば、テキスト量が増えたり画面が狭くなって折り返されたりしても、箱自身が中身の量に合わせて自動的に縦に伸びてくれるため、絶対に文字がはみ出すことはありません。
HTMLコード表示
<div class="hsz1-wrapper">
<input type="radio" name="hsz1-state" id="hpos1-fixed" class="hsz1-radio" checked>
<input type="radio" name="hsz1-state" id="hpos1-auto" class="hsz1-radio">
<div class="hsz1-controls">
<label for="hpos1-fixed" class="hsz1-btn">❌ 高さ固定 (はみ出す)</label>
<label for="hpos1-auto" class="hsz1-btn">⭕️ 高さ自動 (伸びる)</label>
</div>
<div class="hsz1-demo-area">
<div class="hsz1-box target-fixed-hsz1">
<div class="hsz1-code">height: 100px;</div>
<p class="hsz1-text">
テキスト量が増えたり、スマホの狭い画面で折り返されたりして行数が増えると、固定された100pxの高さを超えてしまい、このように箱から文字が盛大にはみ出してレイアウトが崩壊します。
</p>
</div>
<div class="hsz1-box target-auto-hsz1">
<div class="hsz1-code hsz1-code-ok">height: auto;</div>
<p class="hsz1-text">
高さをauto(デフォルト)にしておけば、テキスト量が増えたり画面が狭くなって折り返されたりしても、箱自身が中身の量に合わせて自動的に縦に伸びてくれるため、絶対に文字がはみ出すことはありません。
</p>
</div>
</div>
</div>CSSコード表示
.hsz1-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hsz1-radio {
display: none;
}
.hsz1-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hsz1-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hpos1-fixed:checked ~ .hsz1-controls [for="hpos1-fixed"] {
background-color: #dc3545;
color: white;
}
#hpos1-auto:checked ~ .hsz1-controls [for="hpos1-auto"] {
background-color: #198754;
color: white;
}
.hsz1-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 40px 20px 80px 20px; /* はみ出したテキストを見せるために下余白を多めに */
display: flex;
justify-content: center;
}
/* 共通の箱スタイル(スマホを想定して幅を狭くしています) */
.hsz1-box {
width: 250px;
background-color: #e9ecef;
border: 3px solid #6c757d;
padding: 15px;
border-radius: 4px;
display: none;
box-sizing: border-box;
}
.hsz1-code {
font-family: monospace;
font-weight: bold;
color: #dc3545;
margin-bottom: 10px;
text-align: center;
border-bottom: 1px solid #ccc;
padding-bottom: 5px;
}
.hsz1-code-ok {
color: #198754;
}
.hsz1-text {
font-size: 14px;
color: #333;
line-height: 1.6;
margin: 0;
}
/* ❌ NGスタイル:高さを100pxで固定 */
#hpos1-fixed:checked ~ .hsz1-demo-area .target-fixed-hsz1 {
display: block;
height: 100px;
border-color: #dc3545;
}
#hpos1-fixed:checked ~ .hsz1-demo-area .target-fixed-hsz1 .hsz1-text {
/* はみ出しを強調する(通常は自動ではみ出します) */
overflow: visible;
color: #dc3545;
}
/* ⭕️ OKスタイル:高さは指定しない(auto) */
#hpos1-auto:checked ~ .hsz1-demo-area .target-auto-hsz1 {
display: block;
height: auto;
border-color: #198754;
}高さを100%や画面いっぱいに広げる
画面のファーストビューにフルスクリーンで画像や色を敷きたいとき、高さを100%にして親要素いっぱいに広げたいと考えることがあります。
ただし、よくあるのが「height: 100%;と書いたのに高さが広がらない」という現象です。
パーセント(%)という単位は、「親要素の高さに対して何%か」という意味を持ちます。
そのため、親要素に具体的な高さがなければ、100%の計算基準が存在せず、結果的に中身の分だけの高さ(auto)になります。
ブラウザの画面の高さいっぱいに広げたい場合、実務では%ではなくvhという単位を使用します。
height: 100vh;と指定すれば、親要素の高さに関係なく、強制的に「ブラウザの表示領域の高さの100%」まで広げられます。
親要素(高さ指定なし)
基準となる親の高さがないため計算できず、中身の文字の分しか高さが出ません。
※デモのため50vh(画面の半分の高さ)にしています。親の高さに関係なく、画面基準で大きく広がります。
HTMLコード表示
<div class="hsz2-wrapper">
<input type="radio" name="hsz2-state" id="hsz2-percent" class="hsz2-radio" checked>
<input type="radio" name="hsz2-state" id="hsz2-vh" class="hsz2-radio">
<div class="hsz2-controls">
<label for="hsz2-percent" class="hsz2-btn">❌ height: 100% (効かない)</label>
<label for="hsz2-vh" class="hsz2-btn">⭕️ height: 100vh (広がる)</label>
</div>
<div class="hsz2-demo-area">
<div class="hsz2-parent">
<p class="hsz2-parent-label">親要素(高さ指定なし)</p>
<div class="hsz2-child target-percent-hsz2">
<div class="hsz2-code">height: 100%;</div>
<p>基準となる親の高さがないため計算できず、中身の文字の分しか高さが出ません。</p>
</div>
<div class="hsz2-child target-vh-hsz2">
<div class="hsz2-code hsz2-code-ok">height: 50vh;</div>
<p>※デモのため50vh(画面の半分の高さ)にしています。親の高さに関係なく、画面基準で大きく広がります。</p>
</div>
</div>
</div>
</div>CSSコード表示
.hsz2-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hsz2-radio {
display: none;
}
.hsz2-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hsz2-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hsz2-percent:checked ~ .hsz2-controls [for="hsz2-percent"] {
background-color: #dc3545;
color: white;
}
#hsz2-vh:checked ~ .hsz2-controls [for="hsz2-vh"] {
background-color: #198754;
color: white;
}
.hsz2-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 20px;
}
.hsz2-parent {
border: 3px dotted #adb5bd;
padding: 10px;
background-color: #f1f3f5;
/* ★重要:ここに高さが指定されていない */
}
.hsz2-parent-label {
font-size: 12px;
color: #666;
font-weight: bold;
margin: 0 0 10px 0;
}
.hsz2-child {
color: white;
padding: 20px;
border-radius: 4px;
text-align: center;
display: none;
box-sizing: border-box;
}
.hsz2-child p {
font-size: 14px;
margin: 10px 0 0 0;
line-height: 1.5;
}
.hsz2-code {
font-family: monospace;
font-size: 16px;
font-weight: bold;
background-color: rgba(255,255,255,0.2);
display: inline-block;
padding: 5px 10px;
border-radius: 4px;
}
/* ❌ % の場合 */
#hsz2-percent:checked ~ .hsz2-demo-area .target-percent-hsz2 {
display: block;
background-color: #dc3545;
height: 100%; /* 親の高さがないので効かない */
}
/* ⭕️ vh の場合 */
#hsz2-vh:checked ~ .hsz2-demo-area .target-vh-hsz2 {
display: block;
background-color: #198754;
height: 50vh; /* 画面(ビューポート)の高さを基準にする */
}マージンとパディングで適切な余白を作る
<div>を使ったレイアウトでデザインを決定づけるのが余白のコントロールです。
余白には明確に役割が異なる2種類が存在します。
margin(マージン)
箱の外側の余白。
他の<div>との間に距離を取りたい時に使用します。padding(パディング)
箱の内側の余白。
箱の枠線(背景色)から中に入っているテキストまでの距離を取る時に使用します。
よく破壊するレイアウトの例が「横幅いっぱいにしようとwidth: 100%;を指定した<div>に、内側の余白でpadding: 20px;を追加すると、ブラウザは「100% + 左右の余白40px」と計算し、画面の外へ箱がはみ出して横スクロールバーが出現します。
これを防ぐCSSがbox-sizing: border-box;です。
指定することで、paddingを「widthの100%の内側に含めて計算」し、はみ出しを防げます。
【margin: 20px;】
箱の「外側」に余白ができるため、上の要素との距離が離れました。箱の大きさ自体は変わりません。
HTMLコード表示
<div class="hsz3-wrapper">
<input type="radio" name="hsz3-state" id="hsz3-margin" class="hsz3-radio" checked>
<input type="radio" name="hsz3-state" id="hsz3-padding" class="hsz3-radio">
<input type="radio" name="hsz3-state" id="hsz3-boxsizing" class="hsz3-radio">
<div class="hsz3-controls">
<label for="hsz3-margin" class="hsz3-btn">margin (外側の余白)</label>
<label for="hsz3-padding" class="hsz3-btn">❌ padding (内側の余白・はみ出し)</label>
<label for="hsz3-boxsizing" class="hsz3-btn">⭕️ box-sizing (はみ出し防止)</label>
</div>
<div class="hsz3-demo-area">
<div class="hsz3-sibling">上の要素(ここからの距離に注目)</div>
<div class="hsz3-target-box">
<span class="hsz3-target-text">この箱と文字の余白に注目</span>
</div>
</div>
<div class="hsz3-explanation">
<p id="desc-margin" class="hsz3-desc">【margin: 20px;】<br>箱の「外側」に余白ができるため、上の要素との距離が離れました。箱の大きさ自体は変わりません。</p>
<p id="desc-padding" class="hsz3-desc" style="display:none; color:#dc3545; font-weight:bold;">【padding: 20px; (危険)】<br>箱の「内側」に余白ができました。しかし、width: 100%にpaddingが足されてしまったため、デモエリア(点線)の右側に箱がはみ出しています!</p>
<p id="desc-boxsizing" class="hsz3-desc" style="display:none; color:#198754; font-weight:bold;">【+ box-sizing: border-box; (安全)】<br>この魔法を書くことで、paddingを含めた状態でwidth: 100%に収めてくれるため、右側のはみ出しが直りました。</p>
</div>
</div>CSSコード表示
.hsz3-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hsz3-radio {
display: none;
}
.hsz3-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hsz3-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hsz3-margin:checked ~ .hsz3-controls [for="hsz3-margin"] {
background-color: #0d6efd;
color: white;
}
#hsz3-padding:checked ~ .hsz3-controls [for="hsz3-padding"] {
background-color: #dc3545;
color: white;
}
#hsz3-boxsizing:checked ~ .hsz3-controls [for="hsz3-boxsizing"] {
background-color: #198754;
color: white;
}
.hsz3-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 0;
margin-bottom: 15px;
overflow: hidden;
}
.hsz3-sibling {
background-color: #6c757d;
color: white;
padding: 10px;
text-align: center;
font-size: 14px;
}
/* テスト対象の箱のベーススタイル */
.hsz3-target-box {
background-color: #0d6efd;
color: white;
font-weight: bold;
font-size: 14px;
text-align: center;
width: 100%;
transition: all 0.3s ease;
}
/* margin: 外側の余白 */
#hsz3-margin:checked ~ .hsz3-demo-area .hsz3-target-box {
margin-top: 30px;
background-color: #0d6efd;
padding: 0;
}
/* padding: 内側の余白(わざとはみ出させるNG状態) */
#hsz3-padding:checked ~ .hsz3-demo-area .hsz3-target-box {
margin-top: 0;
background-color: #dc3545;
padding: 30px;
}
/* box-sizing: はみ出しを防ぐ */
#hsz3-boxsizing:checked ~ .hsz3-demo-area .hsz3-target-box {
margin-top: 0;
background-color: #198754;
padding: 30px;
/* ★安全装置をオンにして、paddingを100%の内側に収める */
box-sizing: border-box !important;
}
.hsz3-explanation {
background-color: #fff;
padding: 15px;
border: 1px solid #ccc;
border-radius: 4px;
}
.hsz3-desc {
margin: 0;
font-size: 14px;
line-height: 1.6;
}
#hsz3-margin:checked ~ .hsz3-explanation #desc-margin {
display: block !important;
}
#hsz3-margin:checked ~ .hsz3-explanation #desc-padding,
#hsz3-margin:checked ~ .hsz3-explanation #desc-boxsizing {
display: none !important;
}
#hsz3-padding:checked ~ .hsz3-explanation #desc-padding {
display: block !important;
}
#hsz3-padding:checked ~ .hsz3-explanation #desc-margin,
#hsz3-padding:checked ~ .hsz3-explanation #desc-boxsizing {
display: none !important;
}
#hsz3-boxsizing:checked ~ .hsz3-explanation #desc-boxsizing {
display: block !important;
}
#hsz3-boxsizing:checked ~ .hsz3-explanation #desc-margin,
#hsz3-boxsizing:checked ~ .hsz3-explanation #desc-padding {
display: none !important;
}<div>のデザイン・装飾(背景・枠線・文字)
前述の通り、<div>タグは初期状態では「無色透明の箱」です。
Webサイト上でユーザーに見える形にするには、CSSを用いたデザイン・装飾が必須となります。
箱の背景を塗りつぶしたり、枠線で囲んだり、中に入る文字の見た目を整えたりすることで、「ボタン」「カード」「ヘッダー」といった意味のあるUIパーツが完成します。
- 背景色と背景画像
- 枠線と角丸
<div>内のテキスト装飾と改行のコントロール
文字装飾に関する様々な使い方やまとめを確認したい人は「【html&css】文字装飾に関するWebデザインまとめ」を一読ください。
背景色と背景画像
箱に色をつけるにはbackground-color、画像を箱の背景として敷くにはbackground-imageを使用します。
ただし、background-imageを使って画像を敷いた際、「画像が小さくタイル状に繰り返し表示される」または「画像が大きく一部しか見えない」という失敗が起こります。
これはブラウザの初期仕様によるものです。
背景画像を箱いっぱいに広げるには、画像をどう扱うかを指定するbackground-size: cover;とbackground-position: center;という2つのプロパティをセットで記述するのがよいです。
background-color: #0d6efd;
初期設定では画像がタイル状に繰り返されます。
background-size: cover; で箱にピタッと合わせます。
HTMLコード表示
<div class="hdes1-wrapper">
<input type="radio" name="hdes1-state" id="hdes1-color" class="hdes1-radio" checked>
<input type="radio" name="hdes1-state" id="hdes1-img-bad" class="hdes1-radio">
<input type="radio" name="hdes1-state" id="hdes1-img-good" class="hdes1-radio">
<div class="hdes1-controls">
<label for="hdes1-color" class="hdes1-btn">背景色 (Color)</label>
<label for="hdes1-img-bad" class="hdes1-btn">❌ 背景画像 (調整なし)</label>
<label for="hdes1-img-good" class="hdes1-btn">⭕️ 背景画像 (cover指定)</label>
</div>
<div class="hdes1-demo-area">
<div class="hdes1-box target-color-hdes1">
<div class="hdes1-title">単色の背景</div>
<p class="hdes1-text">background-color: #0d6efd;</p>
</div>
<div class="hdes1-box target-img-bad-hdes1">
<div class="hdes1-title hdes1-text-shadow">画像が繰り返す</div>
<p class="hdes1-text hdes1-text-shadow">初期設定では画像がタイル状に繰り返されます。</p>
</div>
<div class="hdes1-box target-img-good-hdes1">
<div class="hdes1-title hdes1-text-shadow">綺麗に収まる</div>
<p class="hdes1-text hdes1-text-shadow">background-size: cover; で箱にピタッと合わせます。</p>
</div>
</div>
</div>CSSコード表示
.hdes1-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdes1-radio {
display: none;
}
.hdes1-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hdes1-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hdes1-color:checked ~ .hdes1-controls [for="hdes1-color"] {
background-color: #0d6efd;
color: white;
}
#hdes1-img-bad:checked ~ .hdes1-controls [for="hdes1-img-bad"] {
background-color: #dc3545;
color: white;
}
#hdes1-img-good:checked ~ .hdes1-controls [for="hdes1-img-good"] {
background-color: #198754;
color: white;
}
.hdes1-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 20px;
display: flex;
justify-content: center;
}
/* 共通の箱スタイル */
.hdes1-box {
width: 100%;
max-width: 400px;
height: 200px;
padding: 30px 20px;
border-radius: 8px;
box-sizing: border-box;
text-align: center;
color: white;
display: none;
}
.hdes1-title {
font-size: 20px;
margin: 0 0 10px 0;
color: #fff;
}
.hdes1-text {
font-size: 14px;
margin: 0;
line-height: 1.5;
}
/* 背景画像の上に文字を載せるため、文字に影をつけて読みやすくする */
.hdes1-text-shadow {
text-shadow: 0 2px 4px rgba(0,0,0,0.8);
}
/* 1. 背景色 */
#hdes1-color:checked ~ .hdes1-demo-area .target-color-hdes1 {
display: block;
background-color: #0d6efd;
}
/* 2. 背景画像(調整なしのNG例) */
#hdes1-img-bad:checked ~ .hdes1-demo-area .target-img-bad-hdes1 {
display: block;
/* 小さめのダミー画像をタイル状に繰り返す */
background-image: url('https://placehold.co/100x100/343a40/fff?text=Pattern');
}
/* 3. 背景画像(調整ありのOK例) */
#hdes1-img-good:checked ~ .hdes1-demo-area .target-img-good-hdes1 {
display: block;
background-image: url('https://placehold.co/600x400/198754/fff?text=Beautiful+Image');
background-size: cover; /* 箱のサイズに合わせて隙間なく広げる魔法 */
background-position: center; /* 画像の中央を基準にする */
background-repeat: no-repeat; /* 念のため繰り返しをオフ */
}画像における<picture>タグの使い方を知りたい人は「【HTML】<picture>タグの使い方:imgとの違い・レスポンシブ対応」を一読ください。
枠線と角丸
箱の周囲に枠線を引くにはborderプロパティを使用します。
また、Webデザインで多用される「角を丸くする」装飾にはborder-radiusプロパティを使います。
初心者が「border-color: red;と書いたのに枠線が出ない。」と悩む原因は、線の種類を指定していないからです。
CSSでは線の種類(実線solid、点線dottedなど)を明記しないと枠線は描画されません。
実務では、太さ・種類・色を1行でまとめて書くショートハンド(例:border: 2px solid #333;)を使うのが一般的です。
枠線や角丸を使うと、情報がグループ化され、見やすいデザインになります。
HTMLコード表示
<div class="hdes2-wrapper">
<input type="radio" name="hdes2-state" id="hdes2-none" class="hdes2-radio" checked>
<input type="radio" name="hdes2-state" id="hdes2-border" class="hdes2-radio">
<input type="radio" name="hdes2-state" id="hdes2-radius" class="hdes2-radio">
<div class="hdes2-controls">
<label for="hdes2-none" class="hdes2-btn">枠線なし</label>
<label for="hdes2-border" class="hdes2-btn">枠線 (border)</label>
<label for="hdes2-radius" class="hdes2-btn">角丸 (border-radius)</label>
</div>
<div class="hdes2-demo-area">
<div class="hdes2-box target-box-hdes2">
<div class="hdes2-title">お知らせ</div>
<p class="hdes2-text">枠線や角丸を使うと、情報がグループ化され、見やすいデザインになります。</p>
</div>
</div>
</div>CSSコード表示
.hdes2-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdes2-radio {
display: none;
}
.hdes2-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hdes2-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
/* ラジオボタン選択時のボタン色変化 */
#hdes2-none:checked ~ .hdes2-controls [for="hdes2-none"],
#hdes2-border:checked ~ .hdes2-controls [for="hdes2-border"],
#hdes2-radius:checked ~ .hdes2-controls [for="hdes2-radius"] {
background-color: #0dcaf0;
color: #000;
}
.hdes2-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 40px 20px;
display: flex;
justify-content: center;
}
/* 基本の箱(枠線なし状態) */
.hdes2-box {
width: 100%;
max-width: 300px;
background-color: #fff;
padding: 20px;
transition: all 0.3s ease;
}
.hdes2-title {
margin: 0 0 10px 0;
font-size: 18px;
color: #333;
}
.hdes2-text {
margin: 0;
font-size: 14px;
color: #666;
line-height: 1.5;
}
/* 枠線あり(ショートハンドで一括指定) */
#hdes2-border:checked ~ .hdes2-demo-area .target-box-hdes2 {
border: 3px solid #0dcaf0; /* 太さ 種類 色 */
border-radius: 0;
}
/* 角丸あり */
#hdes2-radius:checked ~ .hdes2-demo-area .target-box-hdes2 {
border: 3px solid #0dcaf0;
border-radius: 15px; /* 角を15px分丸くする */
}<div>内のテキスト装飾と改行のコントロール
<div>の中に配置するテキストは、文字サイズを変更するfont-sizeや文字色を変更するcolorで装飾します。
実務で重要になるのがテキストの「折り返し・改行」の制御です。
通常、ブラウザは箱の右端まで文字が来ると自動で改行します。
しかし、URLのような「半角英数字の長い連続」は、英単語の途中で改行してはいけないというルールで箱を突き破って右側にはみ出す性質があります。
この「半角英数字のはみ出し」を防ぐには、強制的に単語の途中で改行させるoverflow-wrap: anywhere;(または word-wrap: break-word;)を親の<div>に指定します。
逆に、ブログの記事一覧などで「タイトルが長すぎる場合は改行しないで、末尾を『…』にして1行で隠したい」という要望もよくあります。
この場合は、white-space: nowrap;とoverflow: hidden;、 text-overflow: ellipsis;の3つのCSSをセットで指定するのが実務で活躍します。
https://example.com/verylongurlthatbreaksthelayoutbecauseithasnospaces1234567890
HTMLコード表示
<div class="hdes3-wrapper">
<input type="radio" name="hdes3-state" id="hdes3-bad" class="hdes3-radio" checked>
<input type="radio" name="hdes3-state" id="hdes3-wrap" class="hdes3-radio">
<input type="radio" name="hdes3-state" id="hdes3-ellipsis" class="hdes3-radio">
<div class="hdes3-controls">
<label for="hdes3-bad" class="hdes3-btn">❌ 対策なし (URLはみ出し)</label>
<label for="hdes3-wrap" class="hdes3-btn">⭕️ 強制改行 (break-word)</label>
<label for="hdes3-ellipsis" class="hdes3-btn">✨ 1行で省略 (...にする)</label>
</div>
<div class="hdes3-demo-area">
<div class="hdes3-box target-text-hdes3">
<div class="hdes3-label">参考URL:</div>
<p class="hdes3-long-text">
https://example.com/verylongurlthatbreaksthelayoutbecauseithasnospaces1234567890
</p>
</div>
</div>
</div>CSSコード表示
.hdes3-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hdes3-radio {
display: none;
}
.hdes3-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hdes3-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hdes3-bad:checked ~ .hdes3-controls [for="hdes3-bad"] {
background-color: #dc3545;
color: white;
}
#hdes3-wrap:checked ~ .hdes3-controls [for="hdes3-wrap"] {
background-color: #198754;
color: white;
}
#hdes3-ellipsis:checked ~ .hdes3-controls [for="hdes3-ellipsis"] {
background-color: #6f42c1;
color: white;
}
.hdes3-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 40px 20px;
display: flex;
justify-content: center;
/* デモエリア全体が横スクロールしないようにガード */
overflow: hidden;
}
/* 枠となるdiv */
.hdes3-box {
width: 100%;
max-width: 250px; /* わざと幅を狭くする */
background-color: #e9ecef;
border: 2px solid #ccc;
padding: 15px;
border-radius: 4px;
box-sizing: border-box;
}
.hdes3-label {
font-weight: bold;
font-size: 14px;
color: #333;
margin-bottom: 5px;
}
/* 中のテキスト */
.hdes3-long-text {
background-color: #fff;
color: #0d6efd;
font-size: 14px;
margin: 0;
padding: 5px;
border: 1px solid #dee2e6;
/* 共通の遷移アニメーション */
transition: all 0.3s ease;
}
/* ❌ 対策なし:半角英数字は折り返されずにはみ出す */
#hdes3-bad:checked ~ .hdes3-demo-area .hdes3-long-text {
/* overflowをあえて表示してはみ出させる */
overflow: visible;
white-space: normal;
word-wrap: normal;
}
/* ⭕️ 強制改行:長いURLでも箱の右端で強制的に折り返す */
#hdes3-wrap:checked ~ .hdes3-demo-area .hdes3-long-text {
overflow-wrap: anywhere; /* 現代の標準プロパティ */
word-wrap: break-word; /* 古いブラウザ用 */
white-space: normal;
}
/* ✨ 1行省略:改行させず、はみ出した分を「...」にする3点セット */
#hdes3-ellipsis:checked ~ .hdes3-demo-area .hdes3-long-text {
white-space: nowrap; /* 1. 改行を禁止する */
overflow: hidden; /* 2. 箱からはみ出た部分を隠す */
text-overflow: ellipsis; /* 3. 隠れた末尾を「...」にする */
}HTML内の改行や空白の表示方法及びテキストの折り返しを制御するwhite-spaceプロパティを理解したい人は「【html&css】white-spaceの使い方とnowrap・pre・pre-wrapの使い分け」を一読ください。
JS連携!表示/非表示の切り替えやクリック
Webサイトに動きを持たせる際、<div>タグはJavaScriptや実務で主流となっているTypeScriptと連携する「操作の対象(的)」として活躍します。
アコーディオンメニューやタブ切り替え、モーダルウィンドウなど、Webのインタラクティブな機能のほとんどは「<div>の表示・非表示の切り替え」や「中身の書き換え」によって作られています。
ここでは、JSと連携する前の基礎となるCSSによる非表示とJSを用いた動的な操作について解説します。
- CSSで
<div>を非表示にする - JavaScriptで中身(
innerHTML)を書き換える - クリック(
onclick)やホバー時のアクション
CSSで<div>を非表示にする
特定のブロックを画面から消す場合、CSSには大きく分けて2つのプロパティが存在します。
一つがdisplay: none;、もう一つがvisibility: hidden;です。
この2つの違いを理解していないとレイアウト崩れを引き起こします。
visibility: hidden;は、要素を「透明」にするだけで、箱の存在(空間)は残り続けるため、不自然な空白が生まれます。
一方、display: none;は「存在そのものを無かったこと」にするため、後ろの要素が上に詰まります。
アコーディオンメニューやポップアップなど、JavaScriptと連携して「閉じている時は空間ごと消したい」場合には、display: none;を使用します。
【通常表示】
中央のdivが表示されています。
HTMLコード表示
<div class="hjs1-wrapper">
<input type="radio" name="hjs1-state" id="hjs1-show" class="hjs1-radio" checked>
<input type="radio" name="hjs1-state" id="hjs1-none" class="hjs1-radio">
<input type="radio" name="hjs1-state" id="hjs1-hidden" class="hjs1-radio">
<div class="hjs1-controls">
<label for="hjs1-show" class="hjs1-btn">通常表示</label>
<label for="hjs1-none" class="hjs1-btn">⭕️ display: none;</label>
<label for="hjs1-hidden" class="hjs1-btn">❌ visibility: hidden;</label>
</div>
<div class="hjs1-demo-area">
<div class="hjs1-content-box">上の文章</div>
<div class="hjs1-target-box">
消える対象のdivタグ
</div>
<div class="hjs1-content-box">下の文章(この位置に注目!)</div>
</div>
<div class="hjs1-explanation">
<p id="desc-show" class="hjs1-desc">【通常表示】<br>中央のdivが表示されています。</p>
<p id="desc-none" class="hjs1-desc" style="display:none; color:#198754; font-weight:bold;">【display: none;】<br>空間ごと完全に消滅するため、下の文章が自然に上に詰まりました。実務での非表示の基本です。</p>
<p id="desc-hidden" class="hjs1-desc" style="display:none; color:#dc3545; font-weight:bold;">【visibility: hidden;】<br>透明になっただけで空間が残るため、不自然な空白ができてしまっています。</p>
</div>
</div>CSSコード表示
.hjs1-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hjs1-radio {
display: none;
}
.hjs1-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hjs1-btn {
background-color: #e9ecef;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
color: #495057;
transition: 0.2s;
font-size: 14px;
}
#hjs1-show:checked ~ .hjs1-controls [for="hjs1-show"] {
background-color: #6c757d;
color: white;
}
#hjs1-none:checked ~ .hjs1-controls [for="hjs1-none"] {
background-color: #198754;
color: white;
}
#hjs1-hidden:checked ~ .hjs1-controls [for="hjs1-hidden"] {
background-color: #dc3545;
color: white;
}
.hjs1-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 30px 20px;
margin-bottom: 15px;
text-align: center;
}
.hjs1-content-box {
background-color: #dee2e6;
padding: 15px;
border-radius: 4px;
color: #333;
}
.hjs1-target-box {
background-color: #0d6efd;
color: white;
padding: 20px;
margin: 15px 0;
border-radius: 4px;
font-weight: bold;
}
/* ⭕️ display: none; の挙動 */
#hjs1-none:checked ~ .hjs1-demo-area .hjs1-target-box {
display: none !important;
}
/* ❌ visibility: hidden; の挙動 */
#hjs1-hidden:checked ~ .hjs1-demo-area .hjs1-target-box {
visibility: hidden !important;
}
.hjs1-explanation {
background-color: #fff;
padding: 15px;
border: 1px solid #ccc;
border-radius: 4px;
}
.hjs1-desc {
margin: 0;
font-size: 14px;
line-height: 1.6;
}
/* 説明文の切り替え */
#hjs1-show:checked ~ .hjs1-explanation #desc-show {
display: block !important;
}
#hjs1-show:checked ~ .hjs1-explanation #desc-none,
#hjs1-show:checked ~ .hjs1-explanation #desc-hidden {
display: none !important;
}
#hjs1-none:checked ~ .hjs1-explanation #desc-none {
display: block !important;
}
#hjs1-none:checked ~ .hjs1-explanation #desc-show,
#hjs1-none:checked ~ .hjs1-explanation #desc-hidden {
display: none !important;
}
#hjs1-hidden:checked ~ .hjs1-explanation #desc-hidden {
display: block !important;
}
#hjs1-hidden:checked ~ .hjs1-explanation #desc-show,
#hjs1-hidden:checked ~ .hjs1-explanation #desc-none {
display: none !important;
}displayの使い方を詳しく知りたい人は「【html&css】displayの種類は?flexやinline-blockの違い」を一読ください。
JavaScriptで中身(innerHTML)を書き換える
ボタンを押したタイミングで、画面遷移させず<div>の中のテキストやHTML構造を書き換える処理は、Webアプリケーション開発の基本です。
innerHTMLは、渡された文字列の中にHTMLタグ(<strong>や<img>など)が含まれていれば、それをブラウザの画面上にタグとして描画する便利なプロパティです。
しかし、「ユーザーが入力したフォームの文字列」などをinnerHTMLに渡すと、悪意あるユーザーが<script>タグを仕込んでた場合、システム上で危険なプログラムが実行される恐れがあります。(XSS攻撃)
「文字」を書き換えるだけであれば、タグとして解釈されないtextContentプロパティを使うのがよいです。
流し込むデータ: <strong>ハッキング成功!</strong>
※innerHTMLはタグを解釈するため、悪意のあるコードも実行されるリスクがあります。単なる文字の置き換えなら、タグをただの文字として無効化するtextContentを使用してください。
HTMLコード表示
<div class="hjs2-wrapper">
<div class="hjs2-controls">
<button class="hjs2-btn hjs2-btn-danger" onclick="changeDivContent('inner')">❌ innerHTMLで書き換える</button>
<button class="hjs2-btn hjs2-btn-safe" onclick="changeDivContent('text')">⭕️ textContentで書き換える</button>
</div>
<div class="hjs2-demo-area">
<div class="hjs2-label">書き換え対象のdiv:</div>
<div id="hjs2-target" class="hjs2-target-box">
ここをクリックで書き換えます。
</div>
</div>
<div class="hjs2-explanation">
<p class="hjs2-desc">
流し込むデータ: <code><strong>ハッキング成功!</strong></code>
</p>
<p class="hjs2-note">
※innerHTMLはタグを解釈するため、悪意のあるコードも実行されるリスクがあります。単なる文字の置き換えなら、タグをただの文字として無効化するtextContentを使用してください。
</p>
</div>
</div>CSSコード表示
.hjs2-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hjs2-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.hjs2-btn {
all: unset !important;
display: inline-block !important;
padding: 10px 15px !important;
border-radius: 4px !important;
cursor: pointer !important;
font-weight: bold !important;
color: white !important;
font-size: 14px !important;
box-sizing: border-box !important;
}
.hjs2-btn-danger {
background-color: #dc3545 !important;
}
.hjs2-btn-safe {
background-color: #198754 !important;
}
.hjs2-demo-area {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 30px 20px;
margin-bottom: 15px;
}
.hjs2-label {
font-size: 14px;
font-weight: bold;
color: #333;
margin-bottom: 10px;
}
.hjs2-target-box {
background-color: #e9ecef;
padding: 20px;
border-radius: 4px;
color: #333;
font-size: 16px;
min-height: 60px;
display: flex;
align-items: center;
}
.hjs2-explanation {
background-color: #fff;
padding: 15px;
border: 1px solid #ccc;
border-radius: 4px;
}
.hjs2-desc {
margin: 0 0 10px 0;
font-size: 14px;
}
.hjs2-desc code {
background-color: #f1f3f5;
padding: 3px 6px;
border-radius: 3px;
color: #d63384;
}
.hjs2-note {
margin: 0;
font-size: 13px;
color: #666;
line-height: 1.5;
}JavaScriptコード表示
function changeDivContent(type) {
const targetDiv = document.getElementById('hjs2-target');
const dangerousString = '<strong>ハッキング成功!</strong>';
if (type === 'inner') {
// タグが解釈されて太字になってしまう(XSSの危険性あり)
targetDiv.innerHTML = dangerousString;
targetDiv.style.backgroundColor = '#f8d7da';
targetDiv.style.color = '#842029';
} else if (type === 'text') {
// タグが無効化され、ただの文字として安全に出力される
targetDiv.textContent = dangerousString;
targetDiv.style.backgroundColor = '#d1e7dd';
targetDiv.style.color = '#0f5132';
}
}クリック(onclick)やホバー時のアクション
CSSの:hover疑似クラスを使えば、マウスカーソルが乗った時に<div>の背景色を変えたり、浮かび上がらせるアニメーションを作れます。
さらに、onclick属性やJavaScriptのイベントリスナーを設定することで、<div>をボタンのように扱うことが可能になります。
初心者が「デザインの調整が楽だから」という理由で、本来<a>(リンク)や<button>(送信や処理)を使うべき箇所を<div>で作ってクリックさせるケースがあります。
しかし、これはUXとアクセシビリティ(誰もが使いやすいWeb)の観点においてよくありません。
視覚障害者の方が利用するスクリーンリーダーにここが押せるボタンであることが伝わりませんし、マウスを使わずキーボードで操作しているユーザーは<div>にフォーカスを当ててEnterキーで押すことが不可能です。
クリックさせるなら<button>タグを使うのがデフォルトですが、tabindex="0"とrole="button"など付与し、キーボードのEnterキーでも発火するようにJSを組むという配慮も求められることを覚えておきましょう。
❌ 悪いボタン化 (アクセシビリティ無視)
※Tabキーで選択できず、スクリーンリーダーにもボタンだと伝わりません。
⭕️ 良いボタン化 (アクセシビリティ対応)
※クリックだけでなく、Tabキーで選択して「Enter」や「Space」キーでも実行できます。
HTMLコード表示
<div class="hjs3-wrapper">
<div class="hjs3-demo-area">
<div class="hjs3-box">
<p class="hjs3-label">❌ 悪いボタン化 (アクセシビリティ無視)</p>
<div class="hjs3-fake-btn hjs3-bad-btn" onclick="alert('クリックされました')">
マウスでしか押せません
</div>
<p class="hjs3-note">※Tabキーで選択できず、スクリーンリーダーにもボタンだと伝わりません。</p>
</div>
<div class="hjs3-box">
<p class="hjs3-label">⭕️ 良いボタン化 (アクセシビリティ対応)</p>
<div class="hjs3-fake-btn hjs3-good-btn" role="button" tabindex="0" onclick="alert('クリックされました')" onkeydown="if(event.key === 'Enter' || event.key === ' ') { alert('キーボードで押されました'); event.preventDefault(); }">
キーボードでも押せます
</div>
<p class="hjs3-note hjs3-note-ok">※クリックだけでなく、Tabキーで選択して「Enter」や「Space」キーでも実行できます。</p>
</div>
</div>
</div>CSSコード表示
.hjs3-wrapper {
background-color: #f8f9fa;
padding: 20px;
border: 1px solid #dee2e6;
border-radius: 4px;
font-family: sans-serif;
}
.hjs3-demo-area {
display: flex;
flex-direction: column;
gap: 20px;
}
.hjs3-box {
background-color: #ffffff;
border: 2px dashed #adb5bd;
padding: 20px;
border-radius: 4px;
text-align: center;
}
.hjs3-label {
font-weight: bold;
margin: 0 0 15px 0;
color: #333;
}
/* divをボタンっぽく見せるCSS */
.hjs3-fake-btn {
display: inline-block;
padding: 15px 30px;
border-radius: 30px;
color: white;
font-weight: bold;
cursor: pointer;
transition: all 0.2s ease;
user-select: none; /* テキスト選択を無効化 */
}
/* ホバー時のアクション(html div hover) */
.hjs3-fake-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
.hjs3-bad-btn {
background-color: #dc3545;
}
.hjs3-good-btn {
background-color: #198754;
}
/* Tabキーでフォーカスされた時の視覚効果(重要) */
.hjs3-good-btn:focus {
outline: 4px solid #86b7fe; /* フォーカスリングを目立たせる */
box-shadow: none;
}
.hjs3-note {
margin: 15px 0 0 0;
font-size: 13px;
color: #dc3545;
text-align: left;
}
.hjs3-note-ok {
color: #198754;
}まとめ
分かりやすいようにまとめを記載します。
- 基本の役割
タグに意味はなく、複数の要素をグループ化し、レイアウトやデザインを適用する「ブロックレベルの箱」として機能する。 - 他のタグとの使い分け
文章の段落には<p>、行内の一部の装飾には<span>、意味のある区切りには<section>を使用し、レイアウト目的にのみ<div>を使う。 - classとidの運用
CSSによるデザインの適用には使い回し可能なclassを使用し、1ページに1度しか使えないidはページ内リンクやJSの起点として用いる。 - 入れ子の注意点
無意味にdivの中にdivを重ねることは避け、CSSの余白調整などを駆使して極力浅い階層を保つ。 - 横並びレイアウト
親要素にdisplay: flex;を指定する手法が標準。
マス目状の分割レイアウトには「CSS Grid」を使用する。 - 配置の調整
箱自体を中央に寄せる際は、幅を指定した上でmargin: 0 auto;を適用する。 - 重なりの制御
要素を重ねる絶対配置には、親要素のposition: relative;と子要素のposition: absolute;をセットで使用する。 - サイズの最適化
スマホ対応時の文字あふれを防ぐため、高さは原則固定せず、中身に合わせて伸びるようにする。 - 余白の管理
外側の余白はmargin、内側の余白はpaddingを使用。paddingによる要素の横幅はみ出しはbox-sizing: border-box;で防ぐ。 - 長い文字列の制御
URLなどの長い半角英数字によるレイアウト崩れは、overflow-wrap: anywhere;等を用いて折り返させる。 - 表示とJS連携
空間ごと要素を非表示にする場合はdisplay: none;を使用。
JSで中身の文字を書き換える際は、XSS対策としてtextContentを使う。
よくある質問(FAQ)
divタグとspanタグ、pタグの違いは何ですか?
役割と「箱の広がり方」が異なります。<div>は「デザインを作る大きな箱(ブロックレベル要素)」で、前後に改行が入ります。
<span>は「文章の一部を装飾する小さな箱(インライン要素)」で、改行されずに文字に寄り添います。
<p>は「ひとつの段落(文章のまとまり)」を表すタグです。
文章には<p>を使い、レイアウト目的でグループ化する際に<div>を使うのが正しい使い分けです。
divタグ自体に何か意味(SEO効果など)はありますか?
いいえ、<div>タグ自体には「見出し」や「段落」といった特別な意味(セマンティクス)は一切ありません。
そのため、検索エンジンにコンテンツの内容を伝えるSEO効果も持ちません。
CSSでデザインを適用したり、JavaScriptで動かす「無色透明なグループ化の箱」として使用します。
意味を持たせたい場合は、<section>や<article>などのHTML5タグの使用を検討してください。
複数のdivタグを横並びにする一番簡単な方法は何ですか?
現代のWeb制作において標準的な方法は「Flexbox(フレックスボックス)」を使うことです。
横に並べたい複数の<div>を、さらに大きな親の<div>で囲み、その親に対してCSSでdisplay: flex; を指定するだけで、中の要素が左から右へと横並びになります。
昔使われていたfloatというプロパティはレイアウト崩れの原因になるため現在は非推奨です。
divの箱を画面の中央(ど真ん中)に配置するにはどうすればいいですか?
目的によって指定するCSSが異なります。
箱の中の「テキスト」を中央にしたい場合はtext-align: center;を使います。
「箱」を左右の中央に配置したい場合は、箱に横幅(width)を指定した上でmargin: 0 auto;を指定します。
画面の「上下左右すべての真ん中」に配置したい場合は、親要素にdisplay: flex; justify-content: center; align-items: center;を指定するのが確実です。
divタグは何重にも入れ子にして使いすぎても大丈夫ですか?
必要以上の入れ子は避けるべきです。
この状態は「divスープ」と呼ばれ、コードが読みづらくなり、修正するのが困難になります。
また、ブラウザの描画スピードにも悪影響を及ぼす可能性があります。
CSSの余白(marginやpadding)を活用し、少ない階層で書くのがよいです。

