Webサイトに奥行きや浮遊感を与え、デザインのクオリティを引き上げるCSSのbox-shadowがあります。
本記事では、基本の書き方からマテリアルデザイン風の多重シャドウ、特定方向へのコントロール、ホバー時の滑らかなアニメーション実装まで解説します。
また、CSSに関するカテゴリーページから学びたい内容を決めたい人は、以下のCSSページをご確認ください。
box-shadowとは:書き方と各値の意味
Webサイトの要素に影を落とし、画面上に奥行きや浮遊感を生み出すのがbox-shadowです。
のっぺりとした平面的なデザインにこのプロパティを足すだけで、ユーザーの目を引くカードUIや、押したくなるボタンを作成できます。
box-shadowの基本構文は、複数の数値と色を組み合わせて1行で記述します。
ここでは、一括指定によるbox-shadowの書き方などを解説します。
- X軸・Y軸・ぼかし・広がり・色の指定
- 透過を使って自然な影にする
drop-shadowとの違い
X軸・Y軸・ぼかし・広がり・色の指定
box-shadowは、基本的に半角スペース区切りで最大5つの値を指定します。
記述する順番はbox-shadow: X軸のズレ Y軸のズレ ぼかし 広がり 色;がルールです。
- X軸(横)のズレ
右方向がプラス、左がマイナス。 - Y軸(縦)のズレ
下方向がプラス、上がマイナス。
このXとYが影の位置を決めます。 - ぼかし
数値を大きくするほど影の輪郭がフワッとぼやけます。 - 広がり
数値を大きくするほど影の面積が要素より大きくなり、マイナスにすると要素より小さく縮みます。 - 色
影の色を指定します。
自然で美しい影を作りたい場合、4つ目の値である「広がり」は基本的に「0(または記述を省略)」にするのがよいです。
また、影の方向は「真上から光が当たっている」と仮定し、X軸のズレを0に、Y軸のズレを少しプラスに設定すると、重力に逆らわない自然な影になります。
⭕️ 各数値(X/Y・blur・spread)が影に与える影響
① X/Y軸のズレ
(右下へ移動)
② ぼかし(blur)
(フワッと広がる)
③ 広がり(spread)
(物理的に大きくなる)
.shadow-offset {
box-shadow: 10px 10px 0 0 #0d6efd;
}
/* ⭕️ 広がり(spread)は0にして、ぼかし(blur)で表現する */
.shadow-blur {
box-shadow: 10px 10px 15px 0 #0d6efd; /* 💡 ぼかしを15px追加 */
}
/* ❌ 広がり(spread)を大きくしすぎると野暮ったくなる */
.shadow-spread {
box-shadow: 10px 10px 15px 10px #0d6efd; /* 💡 影の面積が10px拡張される */
}
HTMLコード表示
<div class="bs-sec1-wrapper">
<p class="bs-caption">⭕️ 各数値(X/Y・blur・spread)が影に与える影響</p>
<div class="bs-demo-area">
<div class="bs-box">
<p class="bs-label">① X/Y軸のズレ<br><small>(右下へ移動)</small></p>
<div class="bs-item is-offset"></div>
</div>
<div class="bs-box">
<p class="bs-label">② ぼかし(blur)<br><small>(フワッと広がる)</small></p>
<div class="bs-item is-blur"></div>
</div>
<div class="bs-box">
<p class="bs-label">③ 広がり(spread)<br><small>(物理的に大きくなる)</small></p>
<div class="bs-item is-spread"></div>
</div>
</div>
<div class="bs-code">
/* 💡 X軸に10px、Y軸に10pxズラす(ぼかし0、広がり0) */<br>
<span class="hl-blue">.shadow-offset</span> {<br>
<span class="hl-red">box-shadow: 10px 10px 0 0 #0d6efd;</span><br>
}<br><br>
/* ⭕️ 広がり(spread)は0にして、ぼかし(blur)で表現する */<br>
<span class="hl-blue">.shadow-blur</span> {<br>
<span class="hl-red">box-shadow: 10px 10px 15px 0 #0d6efd;</span> /* 💡 ぼかしを15px追加 */<br>
}<br><br>
/* ❌ 広がり(spread)を大きくしすぎると野暮ったくなる */<br>
<span class="hl-blue">.shadow-spread</span> {<br>
<span class="hl-red">box-shadow: 10px 10px 15px 10px #0d6efd;</span> /* 💡 影の面積が10px拡張される */<br>
}
</div>
</div>CSSコード表示
.bs-sec1-wrapper {
background-color: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #dee2e6;
}
.bs-caption {
font-size: 13px;
font-weight: bold;
margin-bottom: 20px;
color: #198754;
text-align: center;
}
.bs-demo-area {
display: flex;
flex-wrap: wrap;
gap: 40px;
justify-content: center;
background-color: #e9ecef;
padding: 40px 20px;
border-radius: 4px;
border: 1px dashed #adb5bd;
margin-bottom: 20px;
}
.bs-box {
display: flex;
flex-direction: column;
align-items: center;
width: 150px;
}
.bs-label {
font-size: 12px;
font-weight: bold;
margin-bottom: 15px;
color: #333;
text-align: center;
line-height: 1.4;
}
.bs-item {
width: 80px;
height: 80px;
background-color: #fff;
border: 1px solid #ced4da;
border-radius: 8px;
}
/* 💡 X/Yのズレ */
.is-offset {
/* X Y Blur Spread Color */
box-shadow: 10px 10px 0 0 #0d6efd;
}
/* ⭕️ ぼかし(blur) */
.is-blur {
box-shadow: 10px 10px 15px 0 #0d6efd;
}
/* ❌ 広がり(spread) */
.is-spread {
box-shadow: 10px 10px 15px 10px #0d6efd;
}
.bs-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
border-radius: 4px;
font-family: monospace;
font-size: 13px;
line-height: 1.6;
border-left: 4px solid #0d6efd;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }透過を使って自然な影にする
影を美しく見せるもう一つの重要な要素が「色の透明度」です。
黒い影を作る際、色指定を単なる#000000(真っ黒)や#cccccc(グレー)にしてしまうと、背景色に馴染まず、要素が浮いているというより「黒い汚れがついている」ように見えます。
これを解決するのがrgbaによる透過処理です。
影の透明度をコントロールしたい場合は、影の色指定部分をrgba(0, 0, 0, 0.1)のように記述して色そのものを透過させてください。
さらに実装では、「薄い影をカンマ区切りで複数重ねる(多重シャドウ)」テクニックが主流です。
広がり方の違う薄い影を3〜4層重ねることで、光の散乱に近い、リアルで美しい浮遊感を生み出せます。
⭕️ 影の色(透過)と多重シャドウが生み出すクオリティの差
❌ 透過なしの黒
(汚れのように見える)
⭕️ rgbaによる透過
(背景に馴染む自然な影)
👑 多重シャドウ
(プロの圧倒的リアル感)
.shadow-solid {
box-shadow: 0 10px 15px #000000; /* 💡 黒が強すぎて不自然 */
}
/* ⭕️ rgbaを使って色を10%の濃さ(透明度)にする */
.shadow-rgba {
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
/* 👑 非常に薄い影を複数重ねてリアルな散乱を表現する */
.shadow-multi {
box-shadow:
0 2px 4px rgba(0, 0, 0, 0.05), /* 1層目: 近くて濃い影 */
0 4px 8px rgba(0, 0, 0, 0.05), /* 2層目: 少し広がる影 */
0 8px 16px rgba(0, 0, 0, 0.05), /* 3層目: さらに広がる影 */
0 16px 32px rgba(0, 0, 0, 0.05);/* 4層目: 遠くて薄い影 */
}
HTMLコード表示
<div class="bs-sec2-wrapper">
<p class="bs-caption">⭕️ 影の色(透過)と多重シャドウが生み出すクオリティの差</p>
<div class="bs-demo-area">
<div class="bs-box">
<p class="bs-label">❌ 透過なしの黒<br><small>(汚れのように見える)</small></p>
<div class="bs-item is-solid-black"></div>
</div>
<div class="bs-box">
<p class="bs-label">⭕️ rgbaによる透過<br><small>(背景に馴染む自然な影)</small></p>
<div class="bs-item is-rgba"></div>
</div>
<div class="bs-box">
<p class="bs-label">👑 多重シャドウ<br><small>(プロの圧倒的リアル感)</small></p>
<div class="bs-item is-multi"></div>
</div>
</div>
<div class="bs-code">
/* ❌ 透過(アルファ値)を指定していない */<br>
<span class="hl-blue">.shadow-solid</span> {<br>
<span class="hl-red">box-shadow: 0 10px 15px #000000;</span> /* 💡 黒が強すぎて不自然 */<br>
}<br><br>
/* ⭕️ rgbaを使って色を10%の濃さ(透明度)にする */<br>
<span class="hl-blue">.shadow-rgba</span> {<br>
<span class="hl-red">box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);</span><br>
}<br><br>
/* 👑 非常に薄い影を複数重ねてリアルな散乱を表現する */<br>
<span class="hl-blue">.shadow-multi</span> {<br>
<span class="hl-red">box-shadow:</span><br>
<span class="hl-red">0 2px 4px rgba(0, 0, 0, 0.05),</span> /* 1層目: 近くて濃い影 */<br>
<span class="hl-red">0 4px 8px rgba(0, 0, 0, 0.05),</span> /* 2層目: 少し広がる影 */<br>
<span class="hl-red">0 8px 16px rgba(0, 0, 0, 0.05),</span> /* 3層目: さらに広がる影 */<br>
<span class="hl-red">0 16px 32px rgba(0, 0, 0, 0.05);</span>/* 4層目: 遠くて薄い影 */<br>
}
</div>
</div>CSSコード表示
.bs-sec2-wrapper {
background-color: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #dee2e6;
}
/* ❌ 透過なし(真っ黒) */
.is-solid-black {
box-shadow: 0 10px 15px #000000;
}
/* ⭕️ rgbaによる透過(10%) */
.is-rgba {
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
/* 👑 多重シャドウ */
.is-multi {
box-shadow:
0 2px 4px rgba(0, 0, 0, 0.05),
0 4px 8px rgba(0, 0, 0, 0.05),
0 8px 16px rgba(0, 0, 0, 0.05),
0 16px 32px rgba(0, 0, 0, 0.05);
}drop-shadowとの違い
box-shadowは、その名の通り「要素のBox(四角い箱の境界線)」に対して影をつけます。
しかし、背景が透明に切り抜かれたロゴ画像やCSSのclip-path等で作った「星型」や「吹き出しのしっぽ」にbox-shadowを指定すると、透明なはずの四角い枠に沿って影が出てしまい、不格好な結果になります。
例えば、背景が透明な画像、または複雑なCSS図形の「実際の形(ピクセル・不透明な部分)に沿って影をつけたい」場合は、box-shadowではなく、filter: drop-shadow()を使用してください。
drop-shadow()は画像のアルファチャンネル(透明部分)を自動で認識し、色のある部分だけに正確に影を落としてくれます。
※ただしdrop-shadowには広がりのパラメータがない点に注意が必要です。
⭕️ 透明な画像・図形に対する影のつき方の違い
❌ box-shadow
(四角い枠に影がつく)
⭕️ drop-shadow()
(形に合わせて影がつく)
.transparent-img-wrong {
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.3); /* 💡 透明な四角形の枠に影がついてしまう */
}
/* ⭕️ 透明な画像・図形には drop-shadow を使う */
.transparent-img-correct {
/* 💡 filterプロパティの中で drop-shadow を呼び出す(X Y blur color の順) */
filter: drop-shadow(0 10px 15px rgba(0, 0, 0, 0.3));
}
HTMLコード表示
<div class="bs-sec3-wrapper">
<p class="bs-caption">⭕️ 透明な画像・図形に対する影のつき方の違い</p>
<div class="bs-demo-area">
<div class="bs-box">
<p class="bs-label">❌ box-shadow<br><small>(四角い枠に影がつく)</small></p>
<svg class="bs-star is-box-shadow" viewBox="0 0 24 24" fill="#ffc107" xmlns="http://www.w3.org/2000/svg">
<path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"/>
</svg>
</div>
<div class="bs-box">
<p class="bs-label" style="color:#0d6efd;">⭕️ drop-shadow()<br><small>(形に合わせて影がつく)</small></p>
<svg class="bs-star is-drop-shadow" viewBox="0 0 24 24" fill="#ffc107" xmlns="http://www.w3.org/2000/svg">
<path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"/>
</svg>
</div>
</div>
<div class="bs-code">
/* ❌ 透明な画像に box-shadow を使う */<br>
<span class="hl-blue">.transparent-img-wrong</span> {<br>
<span class="hl-red">box-shadow: 0 10px 15px rgba(0, 0, 0, 0.3);</span> /* 💡 透明な四角形の枠に影がついてしまう */<br>
}<br><br>
/* ⭕️ 透明な画像・図形には drop-shadow を使う */<br>
<span class="hl-blue">.transparent-img-correct</span> {<br>
<span class="hl-comment">/* 💡 filterプロパティの中で drop-shadow を呼び出す(X Y blur color の順) */</span><br>
<span class="hl-red">filter: drop-shadow(0 10px 15px rgba(0, 0, 0, 0.3));</span><br>
}
</div>
</div>CSSコード表示
.bs-sec3-wrapper {
background-color: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #dee2e6;
}
.bs-star {
width: 100px;
height: 100px;
/* 背景がないことを分かりやすくするための透過背景 */
background-image: radial-gradient(rgba(0,0,0,0.05) 10%, transparent 10%);
background-size: 10px 10px;
}
/* ❌ box-shadow:要素の境界ボックス(四角形)に影がつく */
.is-box-shadow {
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.4);
}
/* ⭕️ drop-shadow:中身のアルファチャンネル(形)に沿って影がつく */
.is-drop-shadow {
filter: drop-shadow(0 10px 15px rgba(0, 0, 0, 0.4));
}
.hl-comment { color: #6c757d; font-style: italic; }影の方向と内側のコントロール
CSSで影をつける際、「右下に落とす」という標準的な影の方向だけでなく、「下だけに影をつけたい」「全体を均等に光らせたい」「内側に凹ませたい」といったコントロールが求められる場面があります。
ここでは、X軸・Y軸のオフセットだけでなく、「ぼかし」と「広がり」の計算を利用した方向の限定テクニックや要素を立体的に見せる「内側」の活用法を解説します。
- 特定の方向にのみ影をつける
- 全方向に均等な影をつける方法
insetを使って内側の影を作る
特定の方向にのみ影をつける
ヘッダーの下部やサイドバーの境界線など、「下だけ」や「右だけ」といった指定は、フラットデザインにおいて境界線を明確にするために使われます。
完全に「特定の1辺だけ」に影をつけたい場合は、4つ目の値である「広がり」に、ぼかしの半分から同等の「マイナス値」を指定して、他の辺から影を引っ込めるのがよいです。
例えば下だけならbox-shadow: 0 10px 10px -5px rgba(0,0,0,0.3);と指定します。
⭕️ マイナスspreadを使って、影の「漏れ」を完全に防ぐ
❌ 漏れる影
(左右から黒ずみが見える)
⭕️ 下だけ
(左右から絶対にはみ出さない)
⭕️ 右だけ
(上下から絶対にはみ出さない)
.wrong-bottom {
box-shadow: 0 10px 10px 0 rgba(0, 0, 0, 0.3);
}
/* ⭕️ 下だけ。マイナスspread(-5px)で全体の影を縮め、下(10px)だけ伸ばす */
.correct-bottom-only {
box-shadow: 0 10px 10px -5px rgba(0, 0, 0, 0.3);
}
/* ⭕️ 右だけ。X軸を伸ばし、Y軸を0にする */
.correct-right-only {
box-shadow: 10px 0 10px -5px rgba(0, 0, 0, 0.3);
}
HTMLコード表示
<div class="bs-d-wrapper">
<p class="bs-d-caption">⭕️ マイナスspreadを使って、影の「漏れ」を完全に防ぐ</p>
<div class="bs-d-demo-area">
<div class="bs-d-box">
<p class="bs-d-label">❌ 漏れる影<br><small>(左右から黒ずみが見える)</small></p>
<div class="bs-d-item is-bottom-wrong">下方向のみ?</div>
</div>
<div class="bs-d-box">
<p class="bs-d-label" style="color:#0d6efd;">⭕️ 下だけ<br><small>(左右から絶対にはみ出さない)</small></p>
<div class="bs-d-item is-bottom-correct">下のみ!</div>
</div>
<div class="bs-d-box">
<p class="bs-d-label" style="color:#0d6efd;">⭕️ 右だけ<br><small>(上下から絶対にはみ出さない)</small></p>
<div class="bs-d-item is-right-correct">右のみ!</div>
</div>
</div>
<div class="bs-d-code">
/* ❌ ぼかし(10px)が全方向に広がって漏れてしまう */<br>
<span class="hl-blue">.wrong-bottom</span> {<br>
<span class="hl-red">box-shadow: 0 10px 10px 0 rgba(0, 0, 0, 0.3);</span><br>
}<br><br>
/* ⭕️ 下だけ。マイナスspread(-5px)で全体の影を縮め、下(10px)だけ伸ばす */<br>
<span class="hl-blue">.correct-bottom-only</span> {<br>
<span class="hl-red">box-shadow: 0 10px 10px -5px rgba(0, 0, 0, 0.3);</span><br>
}<br><br>
/* ⭕️ 右だけ。X軸を伸ばし、Y軸を0にする */<br>
<span class="hl-blue">.correct-right-only</span> {<br>
<span class="hl-red">box-shadow: 10px 0 10px -5px rgba(0, 0, 0, 0.3);</span><br>
}
</div>
</div>CSSコード表示
.bs-d-wrapper {
background-color: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #dee2e6;
}
.bs-d-caption {
font-size: 13px;
font-weight: bold;
margin-bottom: 20px;
color: #198754;
text-align: center;
}
.bs-d-demo-area {
display: flex;
flex-wrap: wrap;
gap: 30px;
justify-content: center;
background-color: #e9ecef;
padding: 40px 20px;
border-radius: 4px;
border: 1px dashed #adb5bd;
margin-bottom: 20px;
}
.bs-d-box {
display: flex;
flex-direction: column;
align-items: center;
width: 180px;
}
.bs-d-label {
font-size: 12px;
font-weight: bold;
margin-bottom: 15px;
color: #333;
text-align: center;
line-height: 1.4;
}
.bs-d-item {
width: 120px;
height: 60px;
background-color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 13px;
color: #333;
}
/* ❌ 失敗:左右に影が漏れる */
.is-bottom-wrong {
box-shadow: 0 10px 10px 0 rgba(0, 0, 0, 0.3);
}
/* ⭕️ 成功:下だけ(マイナススプレッド) */
.is-bottom-correct {
box-shadow: 0 10px 10px -5px rgba(0, 0, 0, 0.3);
}
/* ⭕️ 成功:右だけ */
.is-right-correct {
box-shadow: 10px 0 10px -5px rgba(0, 0, 0, 0.3);
}
.bs-d-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
border-radius: 4px;
font-family: monospace;
font-size: 13px;
line-height: 1.6;
border-left: 4px solid #0d6efd;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }全方向に均等な影をつける方法
要素が画面からふわりと浮き上がっているような光の広がりや要素を強調したい時には、全方向に均等な影をつけます。
上下左右すべての中央からの影を作るには、X軸とY軸を0にし、広がりも0にした上で、ぼかしだけを大きくするのがよいです。
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);のように記述することで、要素の中心から全方向に均等で柔らかな後光のような影が生まれます。
⭕️ 全方向(4辺)への美しい均等シャドウ
❌ spreadを使用
(太い枠線のようで汚い)
⭕️ blurのみ使用
(美しく浮き上がる)
.wrong-all-sides {
box-shadow: 0 0 5px 5px rgba(0, 0, 0, 0.2);
}
/* ⭕️ X,Y,spreadをすべて0にし、blurだけを大きくする */
.correct-all-sides {
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.15);
}
HTMLコード表示
<div class="bs-d-wrapper">
<p class="bs-d-caption">⭕️ 全方向(4辺)への美しい均等シャドウ</p>
<div class="bs-d-demo-area">
<div class="bs-d-box">
<p class="bs-d-label">❌ spreadを使用<br><small>(太い枠線のようで汚い)</small></p>
<div class="bs-d-item is-all-wrong" style="border-radius: 50%;"></div>
</div>
<div class="bs-d-box">
<p class="bs-d-label" style="color:#0d6efd;">⭕️ blurのみ使用<br><small>(美しく浮き上がる)</small></p>
<div class="bs-d-item is-all-correct" style="border-radius: 50%;"></div>
</div>
</div>
<div class="bs-d-code">
/* ❌ spread(5px)を指定すると、ぼやけた枠線のように見える */<br>
<span class="hl-blue">.wrong-all-sides</span> {<br>
<span class="hl-red">box-shadow: 0 0 5px 5px rgba(0, 0, 0, 0.2);</span><br>
}<br><br>
/* ⭕️ X,Y,spreadをすべて0にし、blurだけを大きくする */<br>
<span class="hl-blue">.correct-all-sides</span> {<br>
<span class="hl-red">box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.15);</span><br>
}
</div>
</div>CSSコード表示
.bs-d-wrapper {
background-color: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #dee2e6;
}
.bs-d-caption {
font-size: 13px;
font-weight: bold;
margin-bottom: 20px;
color: #198754;
text-align: center;
}
.bs-d-demo-area {
display: flex;
flex-wrap: wrap;
gap: 30px;
justify-content: center;
background-color: #e9ecef;
padding: 40px 20px;
border-radius: 4px;
border: 1px dashed #adb5bd;
margin-bottom: 20px;
}
.bs-d-box {
display: flex;
flex-direction: column;
align-items: center;
width: 180px;
}
.bs-d-label {
font-size: 12px;
font-weight: bold;
margin-bottom: 15px;
color: #333;
text-align: center;
line-height: 1.4;
}
.bs-d-item {
width: 120px;
height: 60px;
background-color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 13px;
color: #333;
}
.is-all-wrong {
/* ❌ spreadを使用 */
box-shadow: 0 0 5px 5px rgba(0, 0, 0, 0.2);
}
.is-all-correct {
/* ⭕️ blurのみ使用 */
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.15);
}
.bs-d-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
border-radius: 4px;
font-family: monospace;
font-size: 13px;
line-height: 1.6;
border-left: 4px solid #0d6efd;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }insetを使って内側の影を作る
box-shadowの先頭(または末尾)にinsetというキーワードを追加すると、影の方向が反転し、要素の「内側」に向かって影が落ちるようになります。
これにより、要素が画面に凹んで埋め込まれているような効果を表現できます。
内側の影を自然に見せるには、透過率を低く(10%前後)し、ぼかしを小さめに設定します。
また、実務では「外側の影」と「内側の影」を同時に指定するテクニックも頻出します。
ボタンを押した時に、外側の影を消し、内側の影を追加することで、物理的なボタンが押し込まれたリアルな表現が可能になります。
特定の内側だけに影をつける際も、マイナスspreadの法則がそのまま使えます。
⭕️ insetを使った「内側」への影と、リアルなボタン挙動
① 基本の内側影
(画面に埋もれた表現)
② 下の内側だけ
(内側でもマイナススプレッド)
③ クリック(Active)で凹む
(長押しで確認してください)
.inset-basic {
box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.2);
}
/* 💡 ② 内側の下辺だけに影をつける(マイナスspreadを活用) */
.inset-bottom-only {
/* Y軸をマイナス(上へ)にし、spreadで縮めることで下から上に伸びる影になる */
box-shadow: inset 0 -10px 10px -5px rgba(0, 0, 0, 0.2);
}
/* ⭕️ ボタンクリック時に外の影を消し、insetを追加する */
.btn {
transform: translateY(0);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); /* 💡 通常時は外側に影 */
transition: all 0.1s;
}
.btn:active {
transform: translateY(4px); /* 💡 影の分だけ下に下げる */
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.2); /* 💡 押されたら内側に影 */
}
HTMLコード表示
<div class="bs-d-wrapper">
<p class="bs-d-caption">⭕️ insetを使った「内側」への影と、リアルなボタン挙動</p>
<div class="bs-d-demo-area">
<div class="bs-d-box">
<p class="bs-d-label">① 基本の内側影<br><small>(画面に埋もれた表現)</small></p>
<div class="bs-d-item is-inset-basic" style="background-color: #f8f9fa;">凹み</div>
</div>
<div class="bs-d-box">
<p class="bs-d-label">② 下の内側だけ<br><small>(内側でもマイナススプレッド)</small></p>
<div class="bs-d-item is-inset-bottom" style="background-color: #f8f9fa;">下だけ凹み</div>
</div>
<div class="bs-d-box">
<p class="bs-d-label">③ クリック(Active)で凹む<br><small>(長押しで確認してください)</small></p>
<button class="bs-d-btn">PUSH ME</button>
</div>
</div>
<div class="bs-d-code">
/* 💡 ① 全方向の内側に影をつける(穴が空いたような凹み) */<br>
<span class="hl-blue">.inset-basic</span> {<br>
<span class="hl-red">box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.2);</span><br>
}<br><br>
/* 💡 ② 内側の下辺だけに影をつける(マイナスspreadを活用) */<br>
<span class="hl-blue">.inset-bottom-only</span> {<br>
<span class="hl-comment">/* Y軸をマイナス(上へ)にし、spreadで縮めることで下から上に伸びる影になる */</span><br>
<span class="hl-red">box-shadow: inset 0 -10px 10px -5px rgba(0, 0, 0, 0.2);</span><br>
}<br><br>
/* ⭕️ ボタンクリック時に外の影を消し、insetを追加する */<br>
<span class="hl-blue">.btn</span> {<br>
<span class="hl-green">transform: translateY(0);</span><br>
<span class="hl-red">box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);</span> /* 💡 通常時は外側に影 */<br>
<span class="hl-green">transition: all 0.1s;</span><br>
}<br>
<span class="hl-blue">.btn:active</span> {<br>
<span class="hl-green">transform: translateY(4px);</span> /* 💡 影の分だけ下に下げる */<br>
<span class="hl-red">box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.2);</span> /* 💡 押されたら内側に影 */<br>
}
</div>
</div>CSSコード表示
/* 💡 ① 基本のinset(凹み) */
.is-inset-basic {
box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.2);
border: none;
}
/* 💡 ② inset bottom only(内側の下辺のみ) */
.is-inset-bottom {
/* insetの場合、Y軸のマイナスが「下辺から上に向かう影」になります */
box-shadow: inset 0 -10px 10px -5px rgba(0, 0, 0, 0.2);
border: none;
}
/* ⭕️ ③ 押せるボタン */
.bs-d-btn {
background-color: #0d6efd;
color: white;
border: none;
border-radius: 8px;
padding: 15px 20px;
font-weight: bold;
cursor: pointer;
/* 通常時は外側(下)に影 */
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
transform: translateY(0);
transition: all 0.1s ease;
}
.bs-d-btn:active {
/* クリック時は影の分(4px)だけ要素を下に下げ、影を内側に切り替える */
transform: translateY(4px);
box-shadow: inset 0 3px 6px rgba(0, 0, 0, 0.4);
}
.hl-comment { color: #6c757d; font-style: italic; }コピペで使える!box-shadowデザイン集
実際のプロジェクトで使えるbox-shadowのデザインは、ある程度パターン化されています。
ここでは、膨大なプリセットの中からWebサイトで実用性が高く、コピペで使える厳選したbox-shadowのテンプレートを紹介します。
- カードやボタンに!マテリアルデザイン風の浮遊感
- カンマ区切りで作る多重シャドウとグラデーション
- ネオンのように光るエフェクトと3Dシャドウ
カードやボタンに!マテリアルデザイン風の浮遊感
Googleが提唱するマテリアルデザインでは、要素の重なりを影の深さで表現します。
box-shadowによるマテリアルデザインは、カードデザインやボタンにおいて標準的で美しいスタイルです。
例えば、ホバーで浮遊感を出したい場合は、通常時の要素に対してtransitionを指定してください。
また、マテリアルデザイン風の浮遊感を出すには、ホバー時に影の色を濃くするのではなく、Y軸のズレとぼかしを大きくするのがよいです。
光源が固定されたまま、要素がカメラに近づいてくる物理法則を再現するためです。
⭕️ ホバーで自然に浮き上がるマテリアルデザイン
マテリアルカード
(ホバーで浮き上がる)
マテリアルボタン
(ホバーで浮き上がる)
.material-card {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
transition: all 0.3s cubic-bezier(.25, .8, .25, 1);
}
.material-card:hover {
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
transform: translateY(-5px); /* 💡 物理的に少し上に移動させる */
}
HTMLコード表示
<div class="bs-preset-wrapper">
<p class="bs-preset-caption">⭕️ ホバーで自然に浮き上がるマテリアルデザイン</p>
<div class="bs-preset-demo-area">
<div class="bs-preset-box">
<p class="bs-preset-label">マテリアルカード<br><small>(ホバーで浮き上がる)</small></p>
<div class="bs-material-card">
Card Content
</div>
</div>
<div class="bs-preset-box">
<p class="bs-preset-label">マテリアルボタン<br><small>(ホバーで浮き上がる)</small></p>
<button class="bs-material-btn">ACTION</button>
</div>
</div>
<div class="bs-preset-code">
/* ⭕️ 通常時にtransitionを指定し、ホバーでY軸とBlurを増やす */<br>
<span class="hl-blue">.material-card</span> {<br>
<span class="hl-red">box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);</span><br>
<span class="hl-green">transition: all 0.3s cubic-bezier(.25, .8, .25, 1);</span><br>
}<br>
<span class="hl-blue">.material-card:hover</span> {<br>
<span class="hl-red">box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);</span><br>
<span class="hl-green">transform: translateY(-5px);</span> /* 💡 物理的に少し上に移動させる */<br>
}
</div>
</div>CSSコード表示
.bs-preset-wrapper {
background-color: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #dee2e6;
}
.bs-preset-caption {
font-size: 13px;
font-weight: bold;
margin-bottom: 20px;
color: #198754;
text-align: center;
}
.bs-preset-demo-area {
display: flex;
flex-wrap: wrap;
gap: 40px;
justify-content: center;
background-color: #e9ecef;
padding: 40px 20px;
border-radius: 4px;
border: 1px dashed #adb5bd;
margin-bottom: 20px;
}
.bs-preset-box {
display: flex;
flex-direction: column;
align-items: center;
}
.bs-preset-label {
font-size: 12px;
font-weight: bold;
margin-bottom: 15px;
color: #333;
text-align: center;
line-height: 1.4;
}
/* 💡 マテリアルカード */
.bs-material-card {
width: 150px;
height: 100px;
background-color: #fff;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: #333;
cursor: pointer;
/* レベル1の影 */
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
/* なめらかな変化 */
transition: all 0.3s cubic-bezier(.25, .8, .25, 1);
}
.bs-material-card:hover {
/* レベル4の深い影に変化 */
box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
/* 実際に少し上に浮かせる */
transform: translateY(-5px);
}
/* 💡 マテリアルボタン */
.bs-material-btn {
background-color: #6200ea; /* マテリアルパープル */
color: white;
border: none;
border-radius: 4px;
padding: 12px 24px;
font-weight: bold;
letter-spacing: 1px;
cursor: pointer;
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2);
transition: all 0.2s ease-in-out;
}
.bs-material-btn:hover {
box-shadow: 0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.2);
transform: translateY(-2px);
}
.bs-preset-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
border-radius: 4px;
font-family: monospace;
font-size: 13px;
line-height: 1.6;
border-left: 4px solid #0d6efd;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }transitionプロパティの使い方を詳しく知りたい人は「【CSS】transitionの使い方:animationやtransformとの違い」を一読ください。
カンマ区切りで作る多重シャドウとグラデーション
影は1つだけしか指定できないわけではありません。
カンマ(,)で区切ることで、複数の影を無限に重ねることができます。
この特性を利用すると、左側は赤、右側は青といった2色のbox-shadowの表現も可能になります。
例えば、グラデーションの影を作りたい場合の解決策は2つです。
- カンマ区切りの多重シャドウで擬似的に作る
左下に赤い影、右下に青い影を配置して混ざり合わせる。 - 疑似要素(
::before)を活用する
要素の裏に同じ大きさの疑似要素を作り、background: linear-gradient(...);とfilter: blur(20px);をかけて、グラデーションの背景をぼかして影のように見せる。
⭕️ linear-gradientが使えない問題を解決する2つのアプローチ
① 2色シャドウ
(カンマ区切りで重ねる)
② グラデーション影
(疑似要素+filter: blur)
.shadow-2-colors {
box-shadow:
-10px 10px 20px rgba(255, 0, 0, 0.5), /* 左下に赤い影 */
10px 10px 20px rgba(0, 0, 255, 0.5); /* 右下に青い影 */
}
/* ⭕️ 完全なグラデーション影は疑似要素とfilterで作る */
.shadow-gradient::before {
content: “”;
position: absolute;
inset: 0; /* 💡 親と同じサイズにする */
background: linear-gradient(45deg, #ff007f, #00d2ff);
filter: blur(15px); /* 💡 グラデーション背景自体をぼかす */
transform: translateY(10px); /* 💡 影として下にズラす */
z-index: -1; /* 💡 要素の裏側に配置 */
}
HTMLコード表示
<div class="bs-preset-wrapper">
<p class="bs-preset-caption">⭕️ linear-gradientが使えない問題を解決する2つのアプローチ</p>
<div class="bs-preset-demo-area">
<div class="bs-preset-box">
<p class="bs-preset-label">① 2色シャドウ<br><small>(カンマ区切りで重ねる)</small></p>
<div class="bs-gradient-multi">2 Colors</div>
</div>
<div class="bs-preset-box">
<p class="bs-preset-label">② グラデーション影<br><small>(疑似要素+filter: blur)</small></p>
<div class="bs-gradient-pseudo">Gradient</div>
</div>
</div>
<div class="bs-preset-code">
/* 💡 ① カンマ区切りで異なる色の影を配置し、混ざり合わせる */<br>
<span class="hl-blue">.shadow-2-colors</span> {<br>
<span class="hl-red">box-shadow:</span><br>
<span class="hl-red">-10px 10px 20px rgba(255, 0, 0, 0.5),</span> /* 左下に赤い影 */<br>
<span class="hl-red">10px 10px 20px rgba(0, 0, 255, 0.5);</span> /* 右下に青い影 */<br>
}<br><br>
/* ⭕️ 完全なグラデーション影は疑似要素とfilterで作る */<br>
<span class="hl-blue">.shadow-gradient::before</span> {<br>
<span class="hl-green">content: "";</span><br>
<span class="hl-green">position: absolute;</span><br>
<span class="hl-green">inset: 0;</span> /* 💡 親と同じサイズにする */<br>
<span class="hl-red">background: linear-gradient(45deg, #ff007f, #00d2ff);</span><br>
<span class="hl-red">filter: blur(15px);</span> /* 💡 グラデーション背景自体をぼかす */<br>
<span class="hl-green">transform: translateY(10px);</span> /* 💡 影として下にズラす */<br>
<span class="hl-green">z-index: -1;</span> /* 💡 要素の裏側に配置 */<br>
}
</div>
</div>CSSコード表示
/* 💡 ① カンマ区切りの2色シャドウ */
.bs-gradient-multi {
width: 120px;
height: 60px;
background-color: #fff;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: #333;
/* 左に赤、右に青の影を配置 */
box-shadow:
-10px 10px 20px rgba(255, 99, 71, 0.6),
10px 10px 20px rgba(65, 105, 225, 0.6);
}
/* ⭕️ ② 疑似要素で作るグラデーションシャドウ */
.bs-gradient-pseudo {
width: 120px;
height: 60px;
background-color: #fff;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: #333;
position: relative; /* 疑似要素の基準 */
z-index: 1; /* 背景に埋もれないようにする */
}
.bs-gradient-pseudo::before {
content: "";
position: absolute;
/* 親と同じサイズにする魔法の記述 */
top: 0; left: 0; right: 0; bottom: 0;
border-radius: 8px;
/* 綺麗なグラデーションを背景に敷く */
background: linear-gradient(45deg, #ff007f, #00d2ff);
/* ぼかして影にする */
filter: blur(15px);
/* 下にずらす */
transform: translateY(5px);
/* 本体の裏側に回す */
z-index: -1;
/* 影の濃さを調整 */
opacity: 0.8;
}ネオンのように光るエフェクトと3Dシャドウ
サイバーパンク風のデザインやゲーミング系のサイトで必須となるのが、発光エフェクトとレトロポップな3Dシャドウです。
- ネオン
本物のネオン管のように光らせるには、カンマ区切りで複数の影を重ねます。
その際、一番内側の影を真っ白にし、外側に向かって対象の色のぼかしを大きくしていくのがコツです。 - 3Dシャドウ
立体的なブロックに見せるには、ぼかしを0にします。1px 1px,2px 2px,3px 3px…と1px刻みで複数の単色の影を重ね合わせることで、ドット絵のような立体ブロックが完成します。
⭕️ テクニックを駆使した光(Glow)と立体(3D)の表現
ネオン(Glow)
(芯を白く、外をぼかす)
ソリッド 3D
(blurを0にして重ねる)
.glow-neon {
background-color: #fff;
box-shadow:
0 0 5px #fff, /* 1層目:芯の光 */
0 0 15px #00f3ff, /* 2層目:強いネオンカラー */
0 0 30px #00f3ff, /* 3層目:広がるネオンカラー */
0 0 50px #00f3ff; /* 4層目:遠くの反射 */
}
/* ⭕️ 3Dブロックはblurを0にして、1px刻みで影を斜めに重ねる */
.solid-3d {
background-color: #ffde00;
border: 2px solid #333;
box-shadow:
1px 1px 0 #333,
2px 2px 0 #333,
3px 3px 0 #333,
4px 4px 0 #333,
5px 5px 0 #333; /* 💡 これで5pxの厚みができる */
}
HTMLコード表示
<div class="bs-preset-wrapper">
<p class="bs-preset-caption">⭕️ テクニックを駆使した光(Glow)と立体(3D)の表現</p>
<div class="bs-preset-demo-area" style="background-color: #212529;">
<div class="bs-preset-box">
<p class="bs-preset-label" style="color: #fff;">ネオン(Glow)<br><small>(芯を白く、外をぼかす)</small></p>
<div class="bs-effect-neon">NEON</div>
</div>
<div class="bs-preset-box">
<p class="bs-preset-label" style="color: #fff;">ソリッド 3D<br><small>(blurを0にして重ねる)</small></p>
<button class="bs-effect-3d">PUSH 3D</button>
</div>
</div>
<div class="bs-preset-code">
/* ⭕️ ネオンは芯を白くし、外側へ向けてぼかしを強くする */<br>
<span class="hl-blue">.glow-neon</span> {<br>
<span class="hl-green">background-color: #fff;</span><br>
<span class="hl-red">box-shadow:</span><br>
<span class="hl-red">0 0 5px #fff,</span> /* 1層目:芯の光 */<br>
<span class="hl-red">0 0 15px #00f3ff,</span> /* 2層目:強いネオンカラー */<br>
<span class="hl-red">0 0 30px #00f3ff,</span> /* 3層目:広がるネオンカラー */<br>
<span class="hl-red">0 0 50px #00f3ff;</span> /* 4層目:遠くの反射 */<br>
}<br><br>
/* ⭕️ 3Dブロックはblurを0にして、1px刻みで影を斜めに重ねる */<br>
<span class="hl-blue">.solid-3d</span> {<br>
<span class="hl-green">background-color: #ffde00;</span><br>
<span class="hl-green">border: 2px solid #333;</span><br>
<span class="hl-red">box-shadow:</span><br>
<span class="hl-red">1px 1px 0 #333,</span><br>
<span class="hl-red">2px 2px 0 #333,</span><br>
<span class="hl-red">3px 3px 0 #333,</span><br>
<span class="hl-red">4px 4px 0 #333,</span><br>
<span class="hl-red">5px 5px 0 #333;</span> /* 💡 これで5pxの厚みができる */<br>
}
</div>
</div>CSSコード表示
/* 💡 ネオンエフェクト(Glow) */
.bs-effect-neon {
color: #fff;
border: 2px solid #fff;
padding: 10px 20px;
font-weight: 900;
font-size: 18px;
border-radius: 8px;
/* 芯は白く、外側はネオンピンク(広がりを変えて重ねる) */
box-shadow:
0 0 5px #fff,
0 0 10px #fff,
0 0 20px #ff00de,
0 0 40px #ff00de,
0 0 80px #ff00de;
/* 文字自体にも光を当てると完璧 */
text-shadow: 0 0 5px #fff, 0 0 10px #ff00de;
}
/* 💡 ソリッド3Dエフェクト */
.bs-effect-3d {
background-color: #ffde00;
color: #333;
border: 2px solid #333;
padding: 12px 24px;
font-weight: 900;
font-size: 16px;
border-radius: 4px;
cursor: pointer;
/* 1px刻みで黒い影を斜めに落としてブロック感を作る */
box-shadow:
1px 1px 0 #f5f5f5,
2px 2px 0 #f5f5f5,
3px 3px 0 #f5f5f5,
4px 4px 0 #f5f5f5,
5px 5px 0 #f5f5f5,
6px 6px 0 #f5f5f5;
transform: translate(0, 0);
transition: all 0.1s ease;
}
/* 押した時に3Dが沈むギミック */
.bs-effect-3d:active {
/* 影の厚みの分だけ移動させる */
transform: translate(4px, 4px);
/* 影を薄く(短く)する */
box-shadow:
1px 1px 0 #333,
2px 2px 0 #333;
}動きを表現するtansformプロパティの使い方を詳しく知りたい人は「【CSS】transformの使い方:移動・回転・拡大と効かない時の対策」を一読ください。
ホバーアニメーションとトラブル解決
Webサイトを訪れたユーザーに「ここはクリックできる」「操作できている」という手応えを与えるために、ホバー(マウスオーバー)時のアニメーションは欠かせません。
しかし、影を動かしたり複雑なレイアウトに組み込んだりすると、「なぜか影が途切れる」「意図した形に影がつかない」といった予期せぬトラブルが頻発します。
ここでは、box-shadowアニメーションの実装方法とバグの解決策を解説します。
transitionでふわっと浮き上がるホバーエフェクトの実装- 影が切れる!
overflowや余白不足の解決策 - 角丸や
clip-pathと組み合わせる際の注意点
transitionでふわっと浮き上がるホバーエフェクトの実装
カードやボタンにカーソルを合わせた際に、ふんわりと影が広がるホバーエフェクトは、Webデザインにおいて多用されるテクニックです。
アニメーションの時間を指定するtransitionは、「通常時(変化する前)の要素」に対して指定してください。
また、ボタンがクリックされた表現を作る際は、外側の影を消しinsetを使って内側の影に切り替えることで、物理的なボタンが押し込まれたリアルな触感を生み出せます。
⭕️ hover時の「浮き上がり」と、active時の「押し込み」
❌ カクつく影
(離した時に一瞬で戻る)
⭕️ 滑らかな影
(戻る時もふわっと)
💡 押し込み
(長押しで確認)
.card-wrong:hover {
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease; /* 💡 ここに書いてはいけない */
}
/* ⭕️ 通常時にtransitionを設定する */
.card-correct {
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease; /* 💡 通常時に書く */
}
.card-correct:hover {
box-shadow: 0 15px 25px rgba(0, 0, 0, 0.2);
transform: translateY(-5px);
}
/* 💡 応用:クリック時(:active)にinsetへ切り替える */
.card-push:active {
transform: translateY(2px);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.2);
}
HTMLコード表示
<div class="bs-hov-wrapper">
<p class="bs-hov-caption">⭕️ hover時の「浮き上がり」と、active時の「押し込み」</p>
<div class="bs-hov-demo-area">
<div class="bs-hov-box">
<p class="bs-hov-label">❌ カクつく影<br><small>(離した時に一瞬で戻る)</small></p>
<div class="bs-hov-item is-wrong">HOVER</div>
</div>
<div class="bs-hov-box">
<p class="bs-hov-label">⭕️ 滑らかな影<br><small>(戻る時もふわっと)</small></p>
<div class="bs-hov-item is-correct">HOVER</div>
</div>
<div class="bs-hov-box">
<p class="bs-hov-label">💡 押し込み<br><small>(長押しで確認)</small></p>
<div class="bs-hov-item is-push">PUSH</div>
</div>
</div>
<div class="bs-hov-code">
/* ❌ hover側にtransitionを書くと離した時にカクつく */<br>
<span class="hl-blue">.card-wrong:hover</span> {<br>
<span class="hl-red">box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);</span><br>
<span class="hl-green">transition: all 0.3s ease;</span> /* 💡 ここに書いてはいけない */<br>
}<br><br>
/* ⭕️ 通常時にtransitionを設定する */<br>
<span class="hl-blue">.card-correct</span> {<br>
<span class="hl-red">box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);</span><br>
<span class="hl-green">transition: all 0.3s ease;</span> /* 💡 通常時に書く */<br>
}<br>
<span class="hl-blue">.card-correct:hover</span> {<br>
<span class="hl-red">box-shadow: 0 15px 25px rgba(0, 0, 0, 0.2);</span><br>
<span class="hl-green">transform: translateY(-5px);</span><br>
}<br><br>
/* 💡 応用:クリック時(:active)にinsetへ切り替える */<br>
<span class="hl-blue">.card-push:active</span> {<br>
<span class="hl-green">transform: translateY(2px);</span><br>
<span class="hl-red">box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.2);</span><br>
}
</div>
</div>CSSコード表示
.bs-hov-wrapper {
background-color: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #dee2e6;
}
.bs-hov-caption {
font-size: 13px;
font-weight: bold;
margin-bottom: 20px;
color: #198754;
text-align: center;
}
.bs-hov-demo-area {
display: flex;
flex-wrap: wrap;
gap: 30px;
justify-content: center;
background-color: #e9ecef;
padding: 40px 20px;
border-radius: 4px;
border: 1px dashed #adb5bd;
margin-bottom: 20px;
}
.bs-hov-box {
display: flex;
flex-direction: column;
align-items: center;
width: 150px;
}
.bs-hov-label {
font-size: 12px;
font-weight: bold;
margin-bottom: 15px;
color: #333;
text-align: center;
line-height: 1.4;
}
.bs-hov-item {
width: 100px;
height: 50px;
background-color: #0d6efd;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 13px;
border-radius: 6px;
cursor: pointer;
}
/* ❌ 失敗:hover側にtransition */
.is-wrong {
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
.is-wrong:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0,0,0,0.3);
transition: all 0.3s ease; /* 離した瞬間にカクつく */
}
/* ⭕️ 成功:通常時にtransition */
.is-correct {
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
/* 💡 戻る時も滑らかに */
transition: all 0.3s ease;
}
.is-correct:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0,0,0,0.3);
}
/* 💡 応用:押し込み(active) */
.is-push {
box-shadow: 0 4px 6px rgba(0,0,0,0.2);
transition: all 0.1s ease; /* アクションは早めが心地よい */
}
.is-push:active {
transform: translateY(2px);
/* 💡 押されたら内側の影へ */
box-shadow: inset 0 3px 6px rgba(0,0,0,0.3);
}
.bs-hov-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
border-radius: 4px;
font-family: monospace;
font-size: 13px;
line-height: 1.6;
border-left: 4px solid #0d6efd;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }改めてtransitionプロパティの使い方を詳しく知りたい人は「【CSS】transitionの使い方:animationやtransformとの違い」を一読ください。
影が切れる!overflowや余白不足の解決策
「指定したはずの影がスパッと切れている」「影が他の要素の後ろに隠れてしまう」といったトラブルは、CSSの仕様を理解していないと何時間も溶かしてしまいます。
影が切れてしまうバグに遭遇した時は、以下の2点を確認・修正してください。
- 親要素の
overflow: hidden;を外すか、親にpaddingを設ける
影が広がる物理的なスペースを余白で作ってあげます。 z-indexとposition: relative;で手前に持ってくる
隣接する要素の後ろに影が潜り込んでいる場合は、ホバーした要素のz-indexを上げて一番手前に持ってくることで解決します。
❌ 影が途切れる原因と、⭕️ 余白・z-indexによる解決策
❌ overflowの罠
(影がスパッと切れる)
⭕️ paddingで解決
(親要素に余白を設ける)
⭕️ z-indexで解決
(隣の要素の上に落とす)
.parent-wrong {
overflow: hidden;
}
/* ⭕️ 解決策1:親要素に影が広がる分のpadding(余白)を設ける */
.parent-correct {
overflow: hidden;
padding: 20px; /* 💡 影の逃げ道を作る */
}
/* ⭕️ 解決策2:隣の要素に影が潜り込む場合は、z-indexで前に出す */
.element-hover:hover {
box-shadow: 0 10px 20px rgba(0,0,0,0.3);
position: relative;
z-index: 10; /* 💡 一番手前に持ってきて影を落とす */
}
HTMLコード表示
<div class="bs-cut-wrapper">
<p class="bs-hov-caption">❌ 影が途切れる原因と、⭕️ 余白・z-indexによる解決策</p>
<div class="bs-hov-demo-area">
<div class="bs-hov-box">
<p class="bs-hov-label">❌ overflowの罠<br><small>(影がスパッと切れる)</small></p>
<div class="bs-cut-stage">
<div class="bs-cut-parent is-hidden">
<div class="bs-cut-item">影が切れる</div>
</div>
</div>
</div>
<div class="bs-hov-box">
<p class="bs-hov-label">⭕️ paddingで解決<br><small>(親要素に余白を設ける)</small></p>
<div class="bs-cut-stage">
<div class="bs-cut-parent is-hidden is-padded">
<div class="bs-cut-item">影が収まる</div>
</div>
</div>
</div>
<div class="bs-hov-box">
<p class="bs-hov-label">⭕️ z-indexで解決<br><small>(隣の要素の上に落とす)</small></p>
<div class="bs-cut-stage">
<div class="bs-cut-sibling-wrap">
<div class="bs-cut-sibling is-z-index">手前</div>
<div class="bs-cut-sibling">奥</div>
</div>
</div>
</div>
</div>
<div class="bs-hov-code">
/* ❌ 原因:親のoverflow: hiddenが影を断ち切る */<br>
<span class="hl-blue">.parent-wrong</span> {<br>
<span class="hl-green">overflow: hidden;</span><br>
}<br><br>
/* ⭕️ 解決策1:親要素に影が広がる分のpadding(余白)を設ける */<br>
<span class="hl-blue">.parent-correct</span> {<br>
<span class="hl-green">overflow: hidden;</span><br>
<span class="hl-green">padding: 20px;</span> /* 💡 影の逃げ道を作る */<br>
}<br><br>
/* ⭕️ 解決策2:隣の要素に影が潜り込む場合は、z-indexで前に出す */<br>
<span class="hl-blue">.element-hover:hover</span> {<br>
<span class="hl-red">box-shadow: 0 10px 20px rgba(0,0,0,0.3);</span><br>
<span class="hl-green">position: relative;</span><br>
<span class="hl-green">z-index: 10;</span> /* 💡 一番手前に持ってきて影を落とす */<br>
}
</div>
</div>CSSコード表示
.bs-cut-wrapper {
background-color: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #dee2e6;
}
.bs-hov-caption {
font-size: 13px;
font-weight: bold;
margin-bottom: 20px;
color: #198754;
text-align: center;
}
.bs-hov-demo-area {
display: flex;
flex-wrap: wrap;
gap: 20px;
justify-content: center;
background-color: #e9ecef;
padding: 30px 10px;
border-radius: 4px;
border: 1px dashed #adb5bd;
margin-bottom: 20px;
}
/* 💡 ボックスのレイアウト(上揃えに変更) */
.bs-hov-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
width: 190px;
}
.bs-hov-label {
font-size: 12px;
font-weight: bold;
margin-bottom: 10px;
color: #333;
text-align: center;
line-height: 1.4;
width: 100%;
height: 35px;
}
.bs-cut-stage {
width: 100%;
height: 120px;
display: flex;
align-items: center;
justify-content: center;
}
/* ❌ 原因:overflow: hidden */
.bs-cut-parent {
width: 90px;
background-color: #fff;
border: 1px solid #adb5bd;
box-sizing: content-box;
}
.bs-cut-parent.is-hidden {
overflow: hidden;
}
/* ⭕️ 解決:paddingでスペース確保 */
.bs-cut-parent.is-padded {
padding: 15px; /* 影の分だけ余白を作る */
}
.bs-cut-item {
width: 100%;
height: 50px;
background-color: #0d6efd;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 11px;
box-shadow: 0 0 15px 5px rgba(0,0,0,0.5); /* 大きな影 */
}
/* 兄弟要素を横に並べるラッパー */
.bs-cut-sibling-wrap {
display: flex;
align-items: center;
justify-content: center;
}
/* 兄弟要素のベース */
.bs-cut-sibling {
width: 60px;
height: 60px;
background-color: #198754;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 12px;
}
/* ⭕️ 解決:z-indexで前に出す */
.bs-cut-sibling.is-z-index {
background-color: #dc3545;
box-shadow: 10px 0 20px 5px rgba(0,0,0,0.6);
position: relative;
z-index: 10; /* 手前に持ってくる */
}
.bs-hov-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
border-radius: 4px;
font-family: monospace;
font-size: 13px;
line-height: 1.6;
border-left: 4px solid #0d6efd;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }それぞれoverflow、padding、z-index、positionプロパティの使い方を詳しく知りたい人は以下から一読ください。
- 【html&css】overflowの使い方とhiddenやscrollの使い分け
- 【html&css】paddingとmarginの違いは?上下左右の余白と順番
- 【html&css】z-indexとは?使い方と効かない時の対処
- 【html&css】positionの使い方とabsolute・fixed・relativeの使い分け
角丸やclip-pathと組み合わせる際の注意点
要素を丸くした場合、基本的にはborder-radiusの形に沿ってbox-shadowも自動的に丸く描画されます。
しかし、近年多用されるclip-pathで複雑な図形に切り抜いた場合は話が変わります。
clip-pathで切り抜いた要素に対して、切り抜かれた形に沿った影を落としたい場合は、box-shadowは使えません。
代わりに、filter: drop-shadow()を使用してください。
drop-shadowであれば、切り抜かれた後の視覚的な形状に対して影を落とします。
⭕️ 角丸への自然な追従と、clip-pathに対するdrop-shadowの活用
💡 border-radius
(自動で丸い影になる)
❌ clip-path
(box-shadowは切り取られる)
⭕️ clip-path
(親にdrop-shadowをかける)
.circle-shape {
border-radius: 50%;
box-shadow: 0 10px 15px rgba(0,0,0,0.5);
}
/* ❌ clip-pathで切り抜くとbox-shadowも一緒に切り捨てられる */
.hexagon-wrong {
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
box-shadow: 0 10px 20px rgba(0,0,0,0.8); /* 💡 まったく見えない */
}
/* ⭕️ 影用の親divを作り、そこに drop-shadow をかける */
.hexagon-correct-wrapper {
/* 💡 親に対して影を落とすことで、ブラウザのバグを回避する */
filter: drop-shadow(0 10px 10px rgba(0,0,0,0.5));
}
.hexagon-correct-inner {
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
}
HTMLコード表示
<div class="bs-clip-wrapper">
<p class="bs-hov-caption">⭕️ 角丸への自然な追従と、clip-pathに対するdrop-shadowの活用</p>
<div class="bs-hov-demo-area">
<div class="bs-hov-box">
<p class="bs-hov-label">💡 border-radius<br><small>(自動で丸い影になる)</small></p>
<div class="bs-clip-stage">
<div class="bs-clip-item is-circle">円形</div>
</div>
</div>
<div class="bs-hov-box">
<p class="bs-hov-label">❌ clip-path<br><small>(box-shadowは切り取られる)</small></p>
<div class="bs-clip-stage">
<div class="bs-clip-item is-hexagon is-box-shadow-wrong">消える</div>
</div>
</div>
<div class="bs-hov-box">
<p class="bs-hov-label" style="color:#0d6efd;">⭕️ clip-path<br><small>(親にdrop-shadowをかける)</small></p>
<div class="bs-clip-stage">
<div class="bs-clip-drop-wrapper">
<div class="bs-clip-item is-hexagon">完璧</div>
</div>
</div>
</div>
</div>
<div class="bs-hov-code">
/* 💡 border-radiusならbox-shadowは自然に丸くなる */<br>
<span class="hl-blue">.circle-shape</span> {<br>
<span class="hl-green">border-radius: 50%;</span><br>
<span class="hl-red">box-shadow: 0 10px 15px rgba(0,0,0,0.5);</span><br>
}<br><br>
/* ❌ clip-pathで切り抜くとbox-shadowも一緒に切り捨てられる */<br>
<span class="hl-blue">.hexagon-wrong</span> {<br>
<span class="hl-green">clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);</span><br>
<span class="hl-red">box-shadow: 0 10px 20px rgba(0,0,0,0.8);</span> /* 💡 まったく見えない */<br>
}<br><br>
/* ⭕️ 影用の親divを作り、そこに drop-shadow をかける */<br>
<span class="hl-blue">.hexagon-correct-wrapper</span> {<br>
<span class="hl-comment">/* 💡 親に対して影を落とすことで、ブラウザのバグを回避する */</span><br>
<span class="hl-red">filter: drop-shadow(0 10px 10px rgba(0,0,0,0.5));</span><br>
}<br>
<span class="hl-blue">.hexagon-correct-inner</span> {<br>
<span class="hl-green">clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);</span><br>
}
</div>
</div>CSSコード表示
.bs-clip-wrapper {
background-color: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #dee2e6;
}
.bs-hov-caption {
font-size: 13px;
font-weight: bold;
margin-bottom: 20px;
color: #198754;
text-align: center;
}
.bs-hov-demo-area {
display: flex;
flex-wrap: wrap;
gap: 20px;
justify-content: center;
background-color: #e9ecef;
padding: 30px 10px;
border-radius: 4px;
border: 1px dashed #adb5bd;
margin-bottom: 20px;
}
/* ボックスのレイアウト(高さを揃える) */
.bs-hov-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
width: 190px;
}
.bs-hov-label {
font-size: 12px;
font-weight: bold;
margin-bottom: 10px;
color: #333;
text-align: center;
line-height: 1.4;
width: 100%;
height: 35px;
}
/* 高さを統一する固定ステージ */
.bs-clip-stage {
width: 100%;
height: 110px;
display: flex;
align-items: center;
justify-content: center;
}
/* ベースの要素 */
.bs-clip-item {
width: 80px;
height: 80px;
background-color: #6f42c1;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 13px;
}
/* 💡 丸い形(border-radius) */
.is-circle {
border-radius: 50%;
box-shadow: 0 10px 15px rgba(0,0,0,0.5);
}
/* 六角形ベース(clip-path) */
.is-hexagon {
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
}
/* ❌ box-shadow(切り取られて見えない) */
.is-box-shadow-wrong {
/* わざと濃い影を指定しても見えない */
box-shadow: 0 10px 20px rgba(0,0,0,0.8);
}
/* ⭕️ drop-shadow用の親ラッパー */
.bs-clip-drop-wrapper {
/* 💡 親要素にフィルターをかけることで確実に影を出す */
filter: drop-shadow(0 10px 10px rgba(0,0,0,0.5));
}
/* コードブロック */
.bs-hov-code {
background-color: #282c34;
color: #abb2bf;
padding: 15px;
border-radius: 4px;
font-family: monospace;
font-size: 13px;
line-height: 1.6;
border-left: 4px solid #0d6efd;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }border-radiusプロパティの使い方を詳しく知りたい人は「【CSS】角丸を作るborder-radiusの使い方:一部指定やボタン実装」を一読ください。
まとめ
分かりやすいようにまとめを記載します。
box-shadowの基本構文は「X軸 Y軸 ぼかし 広がり 色」の順に指定する。- 自然で美しい影を作る場合、「広がり」は0にするのが基本である。
- 影の色は
rgbaを用いて透過させ、背景に馴染ませる。 - カンマ区切りで複数の影を重ねる(多重シャドウ)ことで、よりリアルな質感を表現できる。
- 背景が透明な画像(PNG等)や複雑なCSS図形には、
box-shadowではなくfilter: drop-shadow()を使用する。 - 特定の1辺のみに影を落とす場合、「広がり」にマイナス値を指定して他の辺に漏れる影を隠す。
- 全方向に均等な影をつける場合、X軸・Y軸・広がりをすべて0にし、「ぼかし」のみを適用する。
- 要素の内側に影をつける場合は
insetを先頭(または末尾)に指定する。 - ホバーアニメーションを滑らかにするため、
transitionは:hover側ではなく通常時の要素に指定する。 - 親要素の
overflow: hiddenや余白不足により影が途切れる場合は、親にpaddingを設けて描画領域を確保する。 - 影が隣接要素の下敷きになる場合は、対象要素に
position: relativeとz-indexを指定して手前に配置する。 clip-pathで切り抜かれた要素に影をつける場合は、親要素に対してfilter: drop-shadow()を適用する。
よくある質問(FAQ)
「下だけ」「右だけ」など特定の辺にのみ影をつけるにはどうすればいいですか?
X軸・Y軸のオフセットで方向を決めた後、4つ目の値である「広がり」にマイナス値を指定してください。
例えば下だけに影を落としたい場合、box-shadow: 0 10px 10px -5px rgba(0,0,0,0.2);のように、ぼかしの半分程度のマイナス値をスプレッドに設定すると、上・左・右の辺から影が漏れず、1辺だけに影がつきます。
背景が透明な画像や三角形の図形に影をつけると四角くなってしまいます。
box-shadowは要素の「四角い境界ボックス」に対して影をつける仕様であるためです。
背景が透明な切り抜き画像や、複雑な図形のシルエットに沿って影を落としたい場合は、box-shadowではなくfilter: drop-shadow(X軸 Y軸 ぼかし 色);プロパティを使用してください。
要素の内側(凹んだようなデザイン)に影をつける方法は?
box-shadowの値の先頭、または一番最後にinsetというキーワードを追加してください。
例:box-shadow: inset 0 2px 4px rgba(0,0,0,0.2);
これにより、影が要素の外側ではなく内側に向かって落ちるようになり、入力フォームや押し込まれたボタンのような立体感が生まれます。
複数の影を重ねたり、グラデーションの影を作ることは可能ですか?
複数の影を重ねることは可能です。
box-shadow: 2px 2px 5px red, -2px -2px 5px blue;のように、カンマ(,)で区切ることでいくつでも影を重ねられます。
ただし、box-shadowの色指定としてlinear-gradient等のグラデーションを直接指定することはできません。
グラデーションの影を作りたい場合は、カンマ区切りで複数の色を混ぜ合わせるか、疑似要素(::before)にグラデーション背景を指定してfilter: blur()でぼかすテクニックが必要です。
クリックした時や、フォーカスした時に影を消すにはどう記述しますか?
影を消したい状態の擬似クラス(例::activeや:focus)に対して、box-shadow: none;を指定してください。
例:ボタンを押した時に影を消したい場合は.btn:active { box-shadow: none; transform: translateY(2px); }のように記述します
なお、ブラウザ標準のフォーカスリング(青い枠線)を消したい場合はoutline: none;を併用します。

