1. ホーム
  2. CSS

【CSS】box-shadow の使い方|影で立体感・浮き上がりを表現する方法

Share

カードやボタンがふわっと浮き上がって見えるデザインを、CSS だけで作りたいと思ったことはないでしょうか。その立体感を生み出しているのが box-shadow プロパティです。この記事では、box-shadow の基本的な書き方から、影を構成する 5 つの値(水平・垂直のずれ、ぼかし、広がり、色)の意味、内側に影を入れる inset、複数の影を重ねるテクニック、そして rgba() による半透明の影まで、初心者の方にも分かるように順を追って解説します。カードの浮き上がりやボタンのホバー効果といった実践例も紹介します。

box-shadow とは何か

box-shadow は、要素(ボックス)の周りに影を付けるための CSS プロパティです。影の位置・ぼかし具合・色を自由に指定でき、要素が紙のように浮き上がって見えたり、逆に押し込まれてくぼんで見えたりする表現を、画像を使わずに実現できます。マテリアルデザインのカードや、押せそうに見えるボタンなど、今どきの UI でよく見かける立体感の多くは、このプロパティで作られています。

文字そのものに影を付ける text-shadow という似たプロパティもありますが、box-shadow が対象にするのはあくまで要素の四角い領域(ボックス)です。テキストの影ではなく、要素の輪郭に沿った影が付く点が違いです。まずは影を 1 つ付ける基本形から見ていきましょう。

基本の使い方

もっともシンプルな書き方は、横方向のずれ・縦方向のずれ・色の 3 つを指定する形です。次の例では、要素の右下方向に少しずらした影を付けています。

style.css
.box {
  /* 右に 4px、下に 4px ずらした灰色の影 */
  box-shadow: 4px 4px #888888;
}

これだけでも影は付きますが、輪郭がくっきりした硬い影になります。実際のデザインでは、これにぼかしを加えてやわらかい影にするのが一般的です。次の例のように、3 つめの値としてぼかしの大きさ(blur-radius)を足します。

style.css
.box {
  /* 右下に少しずらし、8px ぼかしたやわらかい影 */
  box-shadow: 4px 4px 8px #888888;
}

ぼかしが入ると、影のふちがなめらかに広がり、ぐっと自然な見た目になります。この「ずれ+ぼかし+色」が、もっともよく使う基本の組み合わせです。

値の構成を理解する

box-shadow の値は、最大で 4 つの長さと 1 つの色を、スペース区切りで並べて指定します。並べる順番が決まっているため、それぞれが何を表すのかを把握しておくことが大切です。基本の書式は box-shadow: offset-x offset-y blur-radius spread-radius color; です。各値の意味を整理すると次のようになります。

意味
offset-x影の水平方向のずれ。正の値で右、負の値で左にずれる。必須。
offset-y影の垂直方向のずれ。正の値で下、負の値で上にずれる。必須。
blur-radius影のぼかしの大きさ。値が大きいほどぼやけて広がる。0 でくっきり。省略時は 0。
spread-radius影の広がり。正の値で影が全方向に大きくなり、負の値で小さくなる。省略時は 0。
color影の色。rgba() などで半透明にできる。省略時の挙動はブラウザ依存。
inset付けると影が要素の内側に入る(くぼみ表現)。省略時は外側の影。

長さの値は前から順に解釈されるため、offset-xoffset-y は必ず指定します。3 つめの長さがあればそれが blur-radius、4 つめがあれば spread-radius です。blur-radiusspread-radius の違いは少し分かりにくいのですが、ぼかしが「ふちをどれだけぼやけさせるか」なのに対し、広がりは「影そのものの面積をどれだけ拡大・縮小するか」だと考えると区別しやすくなります。

rgba() で半透明の影にする

影の色に #888888 のような不透明な色を使うと、背景によっては影が浮いて見えたり、不自然に濃く感じられたりします。実際のデザインでよく使われるのは、黒を半透明にした影です。rgba() を使い、4 つめの値(アルファ値)で透明度を調整します。

style.css
.card {
  /* 黒を 20% の透明度で。背景になじむ自然な影になる */
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

rgba(0, 0, 0, 0.2) は「黒を 20% の濃さで表示する」という意味です。半透明にしておくと、影の下にある背景色がうっすら透けて見えるため、どんな背景の上でも自然になじみます。実務では、影の色はほぼこの形(黒の半透明)を使うと考えてよいでしょう。なお offset-x を 0 にして縦方向のずれだけを付けると、真下に落ちる素直な影になり、カードなどによく合います。

inset で内側の影(くぼみ)を作る

値の先頭に inset キーワードを付けると、影が要素の外側ではなく内側に描かれます。すると、要素が周囲より一段へこんで見える「くぼみ」の表現になります。入力欄を押し込まれたように見せたり、押された状態のボタンを表現したりするのに便利です。

style.css
.well {
  /* inset を付けると影が内側に入り、くぼんで見える */
  box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.3);
}

外側の影とは見え方が逆になる点に注意してください。offset-y を正の値(下方向)にすると、内側の影は上のふち付近に現れます。光が上から当たって、上側がへこんで影になっている、とイメージすると分かりやすいです。

複数の影を重ねる

box-shadow は、影の指定をカンマで区切って並べることで、1 つの要素に複数の影を重ねられます。手前に小さく濃い影、奥に大きくぼかした影、というように 2 つ以上を組み合わせると、より奥行きのあるリアルな立体感を出せます。先に書いた影ほど手前(上)に描画されます。

style.css
.card {
  /* 近い影と遠い影を重ねて、自然な奥行きを出す */
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.15),
    0 8px 24px rgba(0, 0, 0, 0.2);
}

外側の影と inset の影を同時に重ねることもできます。たとえば外側に影を落としつつ、内側にもうっすら影を入れると、立体感とくぼみを両立した複雑な表現が作れます。やりすぎると重く見えるので、まずは 2 つ程度から試すのがおすすめです。

実践例:カードの浮き上がりとボタンのホバー

ここまでの内容を、実際に動くデモで確認してみましょう。下のプレビューには、影の付け方が異なる 4 枚のカードと、ホバーで影が変化するボタンを並べています。標準の影・ぼかしを大きくした影・inset による内側の影・複数の影を重ねたものを見比べてみてください。いちばん下のボタンにマウスを乗せると、影が大きく濃くなりながら少し浮き上がります。CSS タブを開くと、それぞれにどんな box-shadow を指定しているか確認できます。

<div class="demo">
  <div class="card card--basic">
    <p class="label">標準の影</p>
    <p class="value">0 2px 8px rgba(0,0,0,0.2)</p>
  </div>
  <div class="card card--blur">
    <p class="label">大きいぼかし</p>
    <p class="value">0 12px 30px rgba(0,0,0,0.25)</p>
  </div>
  <div class="card card--inset">
    <p class="label">内側の影(inset)</p>
    <p class="value">inset 0 3px 8px rgba(0,0,0,0.3)</p>
  </div>
  <div class="card card--multi">
    <p class="label">複数の影を重ねる</p>
    <p class="value">2つの影をカンマ区切り</p>
  </div>
  <button class="btn">ホバーで影が強まります</button>
</div>
.demo {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 28px;
  padding: 48px 32px;
  background-color: #f3f4f6;
  font-family: sans-serif;
}

/* カード共通のスタイル */
.card {
  width: 200px;
  padding: 24px 20px;
  background-color: #ffffff;
  border-radius: 12px;
}

.label {
  margin: 0 0 8px;
  font-size: 15px;
  font-weight: bold;
  color: #111827;
}

.value {
  margin: 0;
  font-size: 12px;
  color: #6b7280;
  font-family: monospace;
}

/* 標準の影:右下にうっすら落とす定番の指定 */
.card--basic {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

/* ぼかしを大きくすると、より高く浮き上がって見える */
.card--blur {
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.25);
}

/* inset を付けると影が内側に入り、くぼんで見える */
.card--inset {
  box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.3);
}

/* カンマ区切りで複数の影を重ねられる(手前と奥の二重の影) */
.card--multi {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.15),
    0 8px 24px rgba(0, 0, 0, 0.2);
}

/* ボタン:ホバーで影を強め、transition でなめらかに変化させる */
.btn {
  align-self: center;
  padding: 14px 24px;
  font-size: 15px;
  color: #ffffff;
  background-color: #3b82f6;
  border: none;
  border-radius: 10px;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(59, 130, 246, 0.4);
  transition: box-shadow 0.3s ease, transform 0.3s ease;
}

.btn:hover {
  /* 影を大きく濃くし、少し浮かせるとボタンが持ち上がって見える */
  box-shadow: 0 10px 24px rgba(59, 130, 246, 0.5);
  transform: translateY(-3px);
}
Preview

ボタンの例では、box-shadowtransition と組み合わせています。通常時は控えめな影にしておき、:hover で影を大きく濃くしつつ transform: translateY() で少し上に動かすことで、ボタンが指で持ち上がるような効果になります。影だけ、または移動だけでも成立しますが、両方を合わせると押せそうな手触り感がぐっと増します。

影が表示されない・思った見た目にならない原因

box-shadow を書いたのに影が出ない、あるいは想像と違う見た目になる、というつまずきはよくあります。原因はいくつかのパターンに分かれるので、順に確認していきましょう。

ずれもぼかしも 0 で、色しか見えない

offset-xoffset-yblur-radius をすべて 0 にすると、影は要素のちょうど真後ろに同じ大きさで描かれるため、要素に隠れてまったく見えません。影を見せたいときは、最低でも縦か横のずれを付けるか、ぼかしや広がりを指定して、要素の外にはみ出させる必要があります。「影が出ない」と感じたら、まず長さの値が 0 のままになっていないか確認してください。

offset と blur の値の意味を取り違えている

値はスペース区切りで前から順に解釈されます。たとえば box-shadow: 8px #000; のように長さを 1 つしか書かないと、offset-y が足りずにエラー扱いとなり、影が適用されません。最低でも offset-xoffset-y の 2 つの長さが必要です。また、3 つめに書いた値はぼかし、4 つめは広がりとして解釈されるため、ぼかしのつもりで書いた値が広がりに割り当てられて見た目が変わってしまうこともあります。値が思った位置に並んでいるか、順番を確認しましょう。

親要素の overflow: hidden で影が切れる

影は要素の領域の外側に描かれます。そのため、親要素に overflow: hidden が指定されていると、はみ出した影が親の枠でクリッピング(切り取り)され、欠けて見えたりまったく表示されなくなったりします。角丸の画像を切り抜くなどの目的で overflow: hidden を使っている場合に起こりがちです。影を見せたい要素そのものや、その外側の要素に影を移すなど、overflow: hidden の範囲に影が含まれないように構造を見直す必要があります。

色を省略したときの見え方がブラウザによって違う

影の色は省略でき、その場合は currentColor(その要素の文字色)が使われるのが仕様です。ただし、テキストの色をそのまま影に使うと意図しない色になりやすく、結果として「変な色の影が出た」と感じることがあります。影の色は省略せず、rgba(0, 0, 0, 0.2) のように明示的に指定するのが安全です。

まとめ

box-shadow は、要素に影を付けて立体感やくぼみを表現するプロパティです。値は offset-x offset-y blur-radius spread-radius color の順に並べ、最初の 2 つのずれは必須、ぼかしと広がりは省略すると 0 になります。影の色は rgba() で半透明にすると背景になじみ、inset を付ければ内側のくぼみ、カンマ区切りで複数並べれば奥行きのある影が作れます。transition と組み合わせれば、ホバーで影が変化するボタンも簡単です。影が出ないときは、ずれが 0 になっていないか、値の順番、親の overflow: hidden による切れを確認すれば、たいていのつまずきは解決できます。まずはカードに 0 4px 12px rgba(0,0,0,0.2) を付けるところから試してみてください。

参考ページ