CSSのtext-shadowで、文字を浮き上がらせる方法
文字を背景から浮き上がらせるには、text-shadow で、文字の右下に少しずらした影を付けます。影をぼかして半透明にすると、ふんわり浮いて見えます。ぼかさない影を1pxずつずらして重ねると、文字に厚みが出ます。
検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、Chromium 153 です。HTML と CSS のページを Playwright で開き、スクリーンショットの画素、getComputedStyle() の値、要素の大きさを記録しました。Firefox と Safari、スマートフォンの実機は試していません。各ブラウザの対応バージョンは、互換性データ(@mdn/browser-compat-data 8.1.8)の値です。

text-shadow の4つの値
text-shadow には、横のずれ、縦のずれ、ぼかしの半径、影の色の順に書きます。
.shadow-soft {
color: #1f2a30;
text-shadow: 2px 3px 6px rgb(0 0 0 / 0.35);
}
この例では、影を右に 2px、下に 3px ずらし、6px ぼかしています。色は、不透明度 35% の黒(薄い半透明の黒)です。ずれの値をマイナスにすると、影は左や上に出ます。ぼかしの半径は省略でき、省略すると 0(ぼかさない)になります。
ずれの値がそのまま影の位置になることを、四角い文字「■」で確かめました。文字を透明にして、text-shadow: 4px 8px 0 red の赤い影だけを出し、影を付けない黒い文字と比べます。検証環境では、黒い文字の画素の重心が (69.5, 74.0)、赤い影の重心が (73.5, 82.0) で、ちょうど右に 4px、下に 8px ずれていました。
色は、ずれの値の前に書いても後ろに書いても同じです。text-shadow: red 4px 8px と書くと、getComputedStyle() で読んだ値は rgb(255, 0, 0) 4px 8px 0px で、色を後ろに書いたときと同じ形にそろっていました。
影の色は省略しない
色を省略すると、Chromium では文字の色が影の色になりました。文字の色を青にして text-shadow: 12px 0 0 とだけ書くと、getComputedStyle() の値は rgb(0, 0, 255) 12px 0px 0px で、画面にも青い影が右へ 12px 伸びていました。CSS の仕様の box-shadow の節(text-shadow の値もこれに従います)でも、省略した色は currentColor(文字の色)になると書かれています。
ただし、互換性データの注記によると、Safari では色を書いていない影は透明になります。MDN の text-shadow のページでも、ブラウザ間で見た目をそろえるために、色を明示するよう勧めています。影の色はいつも書いておきます。
ぼかしの半径の分だけ、影が外へ広がる
ぼかしの半径を大きくすると、影の縁がぼけて、そのぶん外側まで広がります。「■」の影をずらさずに、ぼかしの半径だけを変えて、白でなくなった画素の範囲を測りました。
| ぼかしの半径 | 影の左端 | 影の上端 | 広がった幅(左側) |
|---|---|---|---|
| 0 | 38px | 42px | 0 |
| 4px | 34px | 38px | 4px |
| 8px | 30px | 34px | 8px |
| 16px | 23px | 28px | 15px |
影は、おおむねぼかしの半径の分だけ外へ広がりました。CSS の仕様のぼかしの節では、ぼかしは、半径の半分を標準偏差にしたガウスぼかしに近づけることになっています。半径 16px では、外側の端の色がほとんど白に近くなり、白と区別できる画素(RGB のどれかが 250 未満)が出ていたのは、左側で 15px、上側で 14px まででした。
影を重ねて、文字に厚みを付ける
text-shadow は、カンマで区切って影をいくつも書けます。ぼかさない影を 1px ずつ右下にずらして重ねると、文字の側面のような厚みが出ます。
.shadow-thick {
color: #00c8e8;
text-shadow:
1px 1px 0 #067a98,
2px 2px 0 #067a98,
3px 3px 0 #067a98,
4px 4px 0 #067a98,
6px 8px 8px rgb(0 0 0 / 0.3);
}
最初の4つが濃い水色の厚みで、最後の1つが、厚みのさらに外側に落ちる、ぼかした影です。
重ねる順番には意味があります。CSS Text Decoration の仕様では、最初に書いた影がいちばん上に描かれます。同じ位置に赤と青の影を重ねて確かめると、10px 10px 0 red, 10px 10px 0 blue では重なった部分が赤、順番を入れ替えると青でした。ぼかした影を最後に書くのは、厚みの下に敷くためです。
影が文字の上に重なることはありません。text-shadow: 0 0 0 red で、黒い文字と同じ位置に赤い影を置いても、文字の真ん中の画素は黒のままでした。
暗い背景で、文字を光らせる
影をずらさずにぼかすと、文字のまわりがぼんやり明るくなります。暗い背景に白い文字を置き、水色の影を2つ重ねると、光っているように見えます。
.shadow-glow {
color: #fff;
background: #1f2a30;
text-shadow:
0 0 4px #00c8e8,
0 0 12px #00c8e8;
}
ぼかしの小さい影で文字の縁を色づけ、ぼかしの大きい影で外側へ光をにじませています。
カーソルを乗せると、文字が浮き上がる
カーソルを乗せたときに、文字を少し上へ動かし、影を大きくすると、文字が持ち上がったように見えます。
.lift {
display: inline-block;
color: #1f2a30;
text-shadow: 1px 1px 2px rgb(0 0 0 / 0.3);
transition: text-shadow 0.2s, transform 0.2s;
}
.lift:hover {
transform: translateY(-3px);
text-shadow: 3px 6px 8px rgb(0 0 0 / 0.3);
}
text-shadow は、transition で途中の値を通りながら変わります。検証環境で <a class="lift"> にカーソルを乗せ、遷移を 0.1 秒の位置で止めて読むと、影は 2.60481px 5.01202px 6.81442px、文字の位置は上へ 2.4px でした。遷移を最後まで進めると、影が 3px 6px 8px、文字の位置が上へ 3px になっていました。
display: inline-block は、<a> や <span> のようなインラインの要素に付けるときに必要です。MDN の transform のページにあるとおり、transform は、置換要素でないインラインボックスには効きません。
影は箱の大きさを変えず、overflow: hidden で切れる
影を付けても、要素の大きさは変わりません。検証環境で、text-shadow: 20px 20px 10px #000 を付けた要素と付けない要素を比べると、getBoundingClientRect() はどちらも幅 140px・高さ 140px で、scrollWidth と scrollHeight も 140px のままでした。CSS Text Decoration の仕様にも、文字の影はレイアウトに影響せず、スクロールできる範囲も広げないと書かれています。
そのため、要素に overflow: hidden を付けると、箱からはみ出た影は切り取られます。

この見出しは、文字の大きさ 48px、line-height: 1 で、影は 4px 8px 6px です。検証環境では、overflow を付けないとき、影は箱の下の端から 8px 下まで出ていました。overflow: hidden を付けると、影は箱の下の端でまっすぐ切れていました。
影を残したいときは、影が出る右と下に padding を足します。この例では、右と下に 12px 足しました。次の CSS では、見出しを1行に収めるために white-space: nowrap も付けています。
.title {
overflow: hidden;
white-space: nowrap;
padding: 0 12px 12px 0;
}
overflow: hidden は、パディングボックスの外側を切り取ります。padding で箱を広げると、影がその中に収まります。検証環境では、箱の高さが 48px から 60px に広がり、影は箱の中で切れずに描かれていました。
text-shadow 自体は古くからあるプロパティで、互換性データでは Chrome 2、Edge 12、Firefox 3.5、Safari 1.1 から使えます。影を複数重ねる書き方は、Safari では 4.0 から使えます。





