- CSS
CSS filter一覧と使い方|blurとbackdrop-filterの違い
CSSのfilterとは、要素そのもの(画像・文字・子要素をまとめて)に、ぼかしや色の変化をかけるプロパティです。 これに対して backdrop-filter は、要素の「後ろに見えているもの」にだけ効果をかけるプロパティで、すりガラスのような表現に使います。名前は似ていますが、効果がかかる場所が正反対です。
この記事では、filterで使える10種類の関数を「変化なしの値・指定できる範囲・単位・見た目の変化」で一覧にしたうえで、同じ色の四角に10関数を当てたときの色を、実際にChromium 141で描画して画素の値を読み取った結果を載せています。指定する順番で色が変わる例、backdrop-filterが効かない条件、blurで端が白くにじむときの直し方も、すべて同じ方法で確かめた数値つきで説明します。
CSS filterの早見表(10関数の値と範囲)
まずは一覧です。「変化なしの値」は、その値を書いても見た目が元のままになる値です。アニメーションの開始点にもこの値を使います。
| 関数 | できること | 変化なしの値 | 指定できる範囲 | 単位 | 値を大きくすると |
|---|---|---|---|---|---|
blur() |
ぼかす | 0 |
0以上(負の値は無効) | px・rem などの長さ(%は無効) | ぼかしが強くなる |
brightness() |
明るさ | 1(100%) |
0以上(上限なし) | 数値または% | 明るくなる。0で真っ黒 |
contrast() |
コントラスト | 1(100%) |
0以上(上限なし) | 数値または% | 明暗の差が強くなる。0で一面グレー |
grayscale() |
白黒にする | 0 |
0〜1(1を超えた値は1として扱われる) | 数値または% | 白黒に近づく。1で完全な白黒 |
hue-rotate() |
色相を回す | 0deg |
制限なし(360degで一周) | deg・turn・rad などの角度 | 色が色相環に沿って変わる |
invert() |
階調を反転 | 0 |
0〜1 | 数値または% | 1で完全に反転。0.5で一面グレー |
opacity() |
透明にする | 1(100%) |
0〜1 | 数値または% | 小さくすると透ける。0で見えなくなる |
saturate() |
彩度 | 1(100%) |
0以上(上限なし) | 数値または% | 鮮やかになる。0で白黒 |
sepia() |
セピア調 | 0 |
0〜1 | 数値または% | 茶色がかった色に近づく |
drop-shadow() |
形に沿った影 | 指定なし | 横・縦のずれ、ぼかし半径(0以上)、色 | 長さと色 | ぼかし半径を大きくすると影が広がる |
filter と backdrop-filter の違いは次のとおりです。
| 比べる点 | filter |
backdrop-filter |
|---|---|---|
| 効果がかかる場所 | その要素自身(中の文字・子要素も含む) | その要素の後ろに見えているもの |
| 要素の中の文字 | 一緒にぼける・色が変わる | そのまま読める |
| 必要な条件 | 特になし | 要素の背景が透明または半透明であること |
| 主な用途 | 画像の加工、ホバー時の変化、影 | すりガラス、固定ヘッダー、モーダルの背景 |
| 使える関数 | 上の10関数 | 同じ10関数 |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CSS filter一覧と使い方|blurとbackdrop-filterの違い」
この記事の確認方法と範囲
数値をどう取ったかを先に書いておきます。
| 項目 | 内容 |
|---|---|
| ブラウザ | Chromium 141.0.7390.37(Playwright 1.56.0 から起動) |
| 方法 | HTMLを描画してスクリーンショットを撮り、指定した座標の画素の色を読み取る |
| 色の見本 | 白い背景の上に置いた rgb(52, 152, 219)(明るい青)の四角 |
| 構文の判定 | CSS.supports() と getComputedStyle() の戻り値 |
| 未実行 | Safari・Firefox での表示、描画時間の計測 |
色の数値は Chromium での結果です。ほかのブラウザでは計算の丸め方によって1〜2程度の差が出ることがあります。
filterの基本の書き方
filter は、プロパティの値に関数を書きます。複数かけるときは半角スペースで区切って並べます。
/* 1つだけ */
.photo { filter: grayscale(1); }
/* 複数(左から順にかかる) */
.photo { filter: grayscale(1) brightness(1.2) blur(2px); }
/* 効果を外す */
.photo:hover { filter: none; }
カンマで区切った書き方は無効な値になり、その行ごと無視されます。Chromium で CSS.supports() を呼んで確かめた結果です。
| 書き方 | 判定 | 説明 |
|---|---|---|
filter: blur(1px) grayscale(1) |
有効 | スペース区切りが正しい形 |
filter: blur(1px), grayscale(1) |
無効 | カンマ区切りは使えない |
filter: blur(-1px) |
無効 | blur に負の値は使えない |
filter: blur(10%) |
無効 | blur に % は使えない |
filter: hue-rotate(90) |
無効 | 角度には単位が必要(90deg) |
filter: hue-rotate(0) |
有効 | 0 だけは単位なしで書ける |
filter: grayscale(-1) |
無効 | 負の値は使えない |
filter: brightness(-1) |
無効 | 負の値は使えない |
filter: grayscale(2) |
有効 | 計算後の値は grayscale(1) になる |
filter: opacity(150%) |
有効 | 計算後の値は opacity(1) になる |
無効な値が1つでも混ざると filter 全体が効かなくなるので、「効かない」ときはまず単位と区切り文字を見直すのが近道です。
かっこの中を空にした場合の計算後の値も確認しました。
| 書いた値 | 計算後の値(Chromium 141) |
|---|---|
grayscale() |
grayscale(1) |
blur() |
blur(0px) |
brightness() |
brightness(1) |
hue-rotate() |
hue-rotate(0deg) |
grayscale() は引数を省くと完全な白黒になり、blur() や brightness() は省くと何も変わりません。読み手が迷わないよう、引数は省略せずに書くことをおすすめします。
10関数を同じ色に当てた結果
白い背景に置いた rgb(52, 152, 219) の四角(100px四方)に、それぞれの filter を当てて四角の中央の色を読み取りました。
| 指定 | 中央の色(計測値) | 見た目 |
|---|---|---|
| なし | rgb(52, 152, 219) |
元の明るい青 |
brightness(0.5) |
rgb(26, 76, 110) |
各色がちょうど半分になり、暗い青に |
brightness(1.5) |
rgb(78, 228, 255) |
1.5倍。青は上限の255で止まり、水色寄りに |
contrast(0.5) |
rgb(90, 140, 173) |
中間のグレーに近づき、くすんだ青に |
contrast(2) |
rgb(0, 177, 255) |
赤が0、青が255まで広がり、くっきりした青に |
grayscale(1) |
rgb(136, 136, 136) |
グレー |
saturate(0) |
rgb(136, 136, 136) |
グレー(grayscale(1) と同じ値) |
saturate(2) |
rgb(0, 168, 255) |
鮮やかな青 |
sepia(1) |
rgb(179, 159, 124) |
黄みがかった茶色 |
hue-rotate(90deg) |
rgb(219, 102, 219) |
ピンク寄りの紫 |
hue-rotate(180deg) |
rgb(219, 119, 52) |
オレンジ |
invert(1) |
rgb(203, 103, 36) |
255から各値を引いた色(オレンジ寄りの茶) |
opacity(0.5) |
rgb(154, 204, 237) |
背景の白と半分ずつ混ざった淡い青 |
blur(4px) |
rgb(52, 152, 219) |
中央は元の色のまま。端だけがにじむ |
drop-shadow(8px 8px 0 #000) |
rgb(52, 152, 219) |
四角は元のまま。右下に黒い影が出る |
この表から読み取れるポイントは次の4つです。
- brightness は各色に同じ数を掛けるだけです。0.5なら 52→26、152→76、219→110 と半分になります。
- grayscale(1) と saturate(0) は同じ結果になりました。白黒にしたいときはどちらでも構いません。
- hue-rotate(180deg) と invert(1) は別の色になります。どちらも「反対の色」に見えますが、invert は明るさも反転するためです。
- blur は面の内側の色を変えません。 変わるのは輪郭の周辺だけです。
blur と drop-shadow は、端と外側の画素を見ると違いがわかります。
| 指定 | 端から1px内側の色 | 四角の右下5px外側の色 |
|---|---|---|
| なし | rgb(52, 152, 219) |
rgb(255, 255, 255) |
blur(4px) |
rgb(126, 189, 232) |
rgb(253, 254, 255) |
drop-shadow(8px 8px 0 #000) |
rgb(52, 152, 219) |
rgb(0, 0, 0) |
blur をかけると、端の色は背景の白と混ざって薄くなり、四角の外側にも色がはみ出します。 これが後半で扱う「端が白くにじむ」現象のもとです。
やりたいこと別の書き方
画像をぼかす(blur)
.photo-blur { filter: blur(4px); }
かっこの中は「ぼかしの半径」です。数字が大きいほど強くぼけます。0.25rem のように rem でも書けます。文字にもかけられるので、読み込み中の仮表示にも使えます。
白黒・セピアにして、ホバーで戻す
.card img {
filter: grayscale(1);
transition: filter 0.3s ease;
}
.card img:hover {
filter: grayscale(0);
}
ホバー後を filter: none ではなく grayscale(0) と書いておくと、同じ関数どうしで数値がなめらかに変わります。 関数の並びが前後でそろっていると、ブラウザは各関数の値を1つずつ補間できます(このアニメーションの動きは一般に知られた仕様に沿った説明で、今回の計測には含めていません)。
暗くして文字を読みやすくする(brightness)
.hero img { filter: brightness(0.6); }
写真の上に白い文字を重ねるときの定番です。黒い半透明の膜を重ねる方法と違い、要素を増やさずに済みます。
アイコンの色を変える(invert / brightness)
/* 黒いアイコンを白に */
.icon-white { filter: invert(1); }
/* どんな色のアイコンも白に */
.icon-white-any { filter: brightness(0) invert(1); }
2つめは「いったん真っ黒にしてから反転する」という順番を利用しています。順番を逆にすると真っ黒になるので、次の節の「順番」の話とあわせて覚えておくと便利です。
形に沿った影をつける(drop-shadow)
.logo { filter: drop-shadow(0 4px 6px rgb(0 0 0 / 0.3)); }
引数は「横のずれ・縦のずれ・ぼかし半径・色」の順です。box-shadow との違いは次の表のとおりです。
| 比べる点 | box-shadow |
filter: drop-shadow() |
|---|---|---|
| 影の形 | 要素の四角い箱(角丸には沿う) | 透明でない部分の形(透過PNGやSVGの輪郭、文字) |
| 広がり(spread)の指定 | できる | できない |
| 内側の影(inset) | できる | できない |
| 複数の影 | カンマで並べる | drop-shadow() をスペースで並べる |
吹き出しのしっぽや、切り抜かれたロゴに影をつけたいときは drop-shadow、カードのような四角い要素には box-shadow が向いています(影の形の違いは一般に知られた仕様で、今回計測したのは四角い要素の影の位置だけです)。
複数指定は順番で結果が変わる
filter に並べた関数は、左から順に、前の結果に対してかかります。 同じ関数の組み合わせでも順番を入れ替えると色が変わります。先ほどと同じ青い四角で計測しました。
| 指定 | 中央の色(計測値) | 見た目 |
|---|---|---|
grayscale(1) sepia(1) |
rgb(183, 163, 127) |
セピア色 |
sepia(1) grayscale(1) |
rgb(161, 161, 161) |
グレー |
brightness(2) contrast(0.5) |
rgb(116, 191, 191) |
落ち着いた青緑 |
contrast(0.5) brightness(2) |
rgb(180, 255, 255) |
ほぼ白に近い水色 |
hue-rotate(90deg) invert(1) |
rgb(36, 153, 36) |
緑 |
invert(1) hue-rotate(90deg) |
rgb(36, 153, 36) |
緑(同じ値) |
1行目と2行目を比べると、最後に grayscale を置くと色味がすべて消えることがわかります。白黒にしてからセピアをかければセピア色になり、セピアにしてから白黒にすればグレーに戻ります。
3行目と4行目は、brightness(2) で 255 を超えた部分が上限で切り取られるタイミングが違うために差が出ています。「明るくしてから差を縮める」のと「差を縮めてから明るくする」のは別の計算です。
一方、5行目と6行目のように、順番を入れ替えても同じ値になる組み合わせもありました。順番で迷ったら、次の考え方で並べると結果を予想しやすくなります。
| 並べる位置 | 置くもの | 理由 |
|---|---|---|
| 先 | 色味を作る関数(sepia、hue-rotate、saturate) | 元の色を材料にして計算するため |
| 中 | 明るさを整える関数(brightness、contrast) | 作った色の見え方を調整するため |
| 後 | blur、drop-shadow、opacity | 形や透け具合は最後にかけるとにじみ方が安定するため |
filterとbackdrop-filterの違いを図とコードで比べる
2つのプロパティは、「どの層に効果がかかるか」が違います。
flowchart TB
subgraph A["filter: blur(8px) をパネルに指定"]
A1["背景の写真<br>そのまま"] --> A2["パネル<br>枠も文字もぼける"]
end
subgraph B["backdrop-filter: blur(8px) をパネルに指定"]
B1["背景の写真<br>パネルの範囲だけぼける"] --> B2["パネル<br>文字はくっきり"]
end
同じ構造で、指定だけを変えて比べられるコードです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>filter と backdrop-filter の比較</title>
<style>
body { margin: 0; font-family: sans-serif; }
.stage {
position: relative;
width: 400px; height: 300px;
background: linear-gradient(90deg, rgb(255, 0, 0) 0 50%, rgb(0, 0, 255) 50% 100%);
margin-bottom: 16px;
}
.panel {
position: absolute; left: 100px; top: 50px;
width: 200px; height: 200px;
display: grid; place-items: center;
background: rgb(255 255 255 / 0.3);
font-weight: bold;
}
.use-filter { filter: blur(20px); }
.use-backdrop { -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px); }
</style>
</head>
<body>
<div class="stage"><div class="panel use-filter">filter</div></div>
<div class="stage"><div class="panel use-backdrop">backdrop-filter</div></div>
</body>
</html>
背景は左半分が赤、右半分が青の縞です。境目(x=200)をまたぐようにパネルを重ね、境目の左右10pxの位置の色を読み取りました。
| パネルの指定 | 境目の左(x=190) | 境目の右(x=210) | 読み取れること |
|---|---|---|---|
| 半透明の白のみ(効果なし) | rgb(255, 77, 77) |
rgb(77, 77, 255) |
赤と青の境目がくっきり見える |
半透明の白 + filter: blur(20px) |
rgb(255, 77, 77) |
rgb(77, 77, 255) |
後ろの縞は変わらない。ぼけるのはパネル自身 |
半透明の白 + backdrop-filter: blur(20px) |
rgb(198, 77, 133) |
rgb(130, 77, 201) |
赤と青が混ざり、後ろの縞がぼけた |
背景なし + backdrop-filter: blur(20px) |
rgb(174, 0, 81) |
rgb(77, 0, 178) |
背景を指定しなくても後ろはぼける |
背景なし + backdrop-filter: grayscale(1) |
rgb(54, 54, 54) |
rgb(18, 18, 18) |
後ろの縞だけが白黒になった |
filter: blur はパネル自身(枠と文字)をぼかし、後ろには手を加えません。backdrop-filter: blur は後ろだけをぼかし、パネルの文字はそのままです。パネルの範囲の外(x=190、y=20)の色は、どの指定でも rgb(255, 0, 0) か、それにごく近い値のままでした。backdrop-filter の効果は要素の範囲の中にだけ現れます。
すりガラス表現のコピペ用コード
そのまま貼って動く、すりガラスのカードです。画像ファイルがなくても確認できるよう、背景はグラデーションにしています。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>すりガラスのカード</title>
<style>
body {
margin: 0; min-height: 100vh;
display: grid; place-items: center;
font-family: sans-serif;
background:
radial-gradient(circle at 20% 30%, #ffb347 0 18%, transparent 19%),
radial-gradient(circle at 75% 65%, #4fc3f7 0 22%, transparent 23%),
linear-gradient(135deg, #5b6ee1, #c850c0);
}
.glass {
width: min(90vw, 360px);
padding: 24px;
border-radius: 16px;
color: #fff;
/* 1. 半透明の背景(これがないと「ただの透明」に見える) */
background: rgb(255 255 255 / 0.18);
/* 2. 後ろをぼかす。接頭辞つきを先、標準を後に書く */
-webkit-backdrop-filter: blur(12px) saturate(1.4);
backdrop-filter: blur(12px) saturate(1.4);
/* 3. 縁の光と影でガラスらしさを足す */
border: 1px solid rgb(255 255 255 / 0.35);
box-shadow: 0 8px 24px rgb(0 0 0 / 0.2);
}
/* backdrop-filter が使えない環境では、背景を濃くして文字を読めるようにする */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
.glass { background: rgb(60 60 90 / 0.85); }
}
</style>
</head>
<body>
<div class="glass">
<h2>お知らせ</h2>
<p>カードの後ろにある模様だけがぼけて、この文字はくっきり読めます。</p>
</div>
</body>
</html>
仕上がりを調整するときの目安です。
| 調整したいこと | 変える場所 | 目安 |
|---|---|---|
| ぼかしの強さ | blur() の値 |
8〜16px。大きいほど後ろの形がわからなくなる |
| ガラスの白さ | 背景の透明度(/ 0.18 の部分) |
0.1〜0.3。大きいほど白く曇る |
| 色の鮮やかさ | saturate() |
1.2〜1.8。ぼかしでくすんだ色を補う |
| 暗いガラスにしたい | 背景を rgb(0 0 0 / 0.3) に |
文字は白のままで読みやすい |
| 固定ヘッダーに使う | position: sticky か fixed を足す |
スクロールで後ろが流れると効果がわかりやすい |
backdrop-filterが効かないときの確認表
もっとも多い原因は背景が不透明になっていることです。先ほどの縞の背景で、パネルの背景を透けない白にして計測しました。
| パネルの指定 | 境目の左(x=190) | 境目の右(x=210) |
|---|---|---|
background: rgb(255 255 255 / 0.3) + backdrop-filter: blur(20px) |
rgb(198, 77, 133) |
rgb(130, 77, 201) |
background: rgb(255, 255, 255) + backdrop-filter: blur(20px) |
rgb(255, 255, 255) |
rgb(255, 255, 255) |
不透明な白にすると、どちらも真っ白になりました。後ろはきちんとぼけているのですが、その上を不透明な背景が塗りつぶしているので見えません。 MDN の backdrop-filter のページにも、効果を見るには要素かその背景を透明または半透明にする必要がある、と書かれています。
直し方は、背景色に透明度をつけるだけです。
/* 直す前:不透明なので後ろが見えない */
.header { background: #ffffff; backdrop-filter: blur(10px); }
/* 直した後:半透明にする */
.header { background: rgb(255 255 255 / 0.6); backdrop-filter: blur(10px); }
そのほかの原因もあわせて、上から順に確認できる表にまとめます。
| 確認する順 | 症状 | 原因 | 直し方 |
|---|---|---|---|
| 1 | まったく変化がない | 背景が不透明(#fff、white、不透明な画像) |
rgb(255 255 255 / 0.6) のように透明度をつける |
| 2 | まったく変化がない | 後ろに何もない(単色の上に置いている) | 単色はぼかしても同じ色。模様や写真の上で確かめる |
| 3 | まったく変化がない | 値の書きまちがい(カンマ区切り、単位なし) | 開発者ツールで打ち消し線がついていないか見る |
| 4 | 少し前の Safari だけ効かない | 接頭辞つきの指定がない | -webkit-backdrop-filter を標準の指定の前に足す |
| 5 | 文字までぼける | backdrop-filter ではなく filter を指定している |
プロパティ名を見直す |
| 6 | 要素が透明になって消える | opacity を要素全体にかけている |
透明度は背景色の側(rgb(... / 0.3))でつける |
| 7 | 効果の範囲が思ったより狭い | 効果は要素の箱の範囲だけ | 要素の大きさを広げる |
開発者ツールの「計算済み」タブで backdrop-filter の値が none になっていれば3番か4番、値が入っているのに見た目が変わらなければ1番か2番、と切り分けられます。
blurで端が白くにじむときの直し方
写真全体に filter: blur() をかけると、端の色が背景と混ざって白っぽく(背景が白の場合)見えます。 ぼかしは周りの画素と色を平均する処理なので、端では「画像の外=何もない部分」が計算に入るためです。
白い背景の上に、緑 rgb(0, 100, 0) の四角(200px四方)を置いて blur(10px) をかけ、左の端の付近の色を読み取りました。
| 方法 | 5px外側 | 端の画素 | 5px内側 | 中央 |
|---|---|---|---|---|
filter: blur(10px) のみ |
rgb(172, 205, 172) |
rgb(112, 168, 112) |
rgb(74, 145, 74) |
rgb(0, 100, 0) |
親に overflow: hidden |
rgb(255, 255, 255) |
rgb(112, 168, 112) |
rgb(74, 145, 74) |
rgb(0, 100, 0) |
親に overflow: hidden + 子に transform: scale(1.1) |
rgb(255, 255, 255) |
rgb(37, 123, 37) |
rgb(19, 112, 19) |
rgb(0, 100, 0) |
親に overflow: hidden + 子を inset: -20px で広げる |
rgb(255, 255, 255) |
rgb(2, 101, 2) |
rgb(0, 100, 0) |
rgb(0, 100, 0) |
上に backdrop-filter: blur(10px) の層を重ねる |
rgb(255, 255, 255) |
rgb(0, 100, 0) |
rgb(0, 100, 0) |
rgb(0, 100, 0) |
読み取れることは3つです。
- blur だけだと、外側に色がはみ出し、端は白と混ざって薄くなります(1行目)。
overflow: hiddenだけでは、はみ出しは止まりますが端の薄さは残ります(2行目)。- ぼかす要素を親より大きくして、にじむ部分を親の外へ追い出すと、端まで元の色に近づきます(3〜4行目)。ぼかし半径10pxに対して20px広げた4行目では、端の画素が
rgb(2, 101, 2)と、元の色とほぼ同じになりました。
コピペ用の形にすると次のようになります。
<div class="blur-box">
<img src="photo.jpg" alt="">
</div>
.blur-box {
position: relative;
width: 400px; height: 260px;
overflow: hidden; /* はみ出した分を隠す */
}
.blur-box img {
position: absolute;
inset: -20px; /* ぼかし半径の2倍ぶん外へ広げる */
width: calc(100% + 40px);
height: calc(100% + 40px);
object-fit: cover;
filter: blur(10px);
}
広げる量の目安は「ぼかし半径の2倍」です。今回の計測では、10pxのぼかしに対して scale(1.1)(200pxの四角では片側10pxぶん)だと端に少し薄さが残り、20px広げるとほぼ消えました。
画像を拡大したくない場合は、5行目の方法が使えます。画像にはフィルターをかけず、上に透明な層を重ねて backdrop-filter でぼかします。
.blur-box { position: relative; }
.blur-box::after {
content: "";
position: absolute; inset: 0;
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
}
この方法では端の画素も rgb(0, 100, 0) のままでした。backdrop-filter は要素の範囲の外にある透明な部分を計算に混ぜないためです。
filterをかけた要素の中で起きること
filter は見た目だけでなく、配置の基準にも影響します。 値が none 以外の filter を持つ要素は、子孫の position: fixed の基準になります。
上から300pxの位置にある親に filter: grayscale(0) を指定し、その中に position: fixed; top: 0 の子を置いて位置を調べました。
| 親の指定 | 子(fixed、top: 0)の画面上端からの位置 |
|---|---|
| filter なし | 0px(画面の上端に固定される) |
filter: grayscale(0) |
300px(親の位置が基準になる) |
見た目が変わらない grayscale(0) でも、基準は親に切り替わりました。 固定ヘッダーやモーダルが思った位置に出ないときは、祖先に filter がかかっていないかを確かめてください。対処は次のどちらかです。
| 対処 | 内容 |
|---|---|
| filter をかける場所を変える | body や大きな枠ではなく、画像など効果が必要な要素だけにかける |
| 固定したい要素を外へ出す | filter のかかった要素の外(body の直下など)に置く |
また、filter のかかった要素は新しい重なりの基準(スタッキングコンテキスト)を作ります。中の子に大きな z-index をつけても、filter のかかった親より手前には出られません。重なり順が合わないときも、同じ2つの対処が使えます(重なり順については一般に知られた仕様で、今回は計測していません)。
ブラウザ対応と-webkit-接頭辞の要否
filter は主要なブラウザで長く使えており、接頭辞なしで書けます。確認が必要なのは backdrop-filter のほうです。
| ブラウザ | 接頭辞なしの backdrop-filter |
補足 |
|---|---|---|
| Chrome | 76 から | Can I use の掲載内容 |
| Edge | 対応(Can I use では 17 から) | 同上 |
| Firefox | 103 から | 同上 |
| Safari / iOS Safari | 18 から | 9〜17 は -webkit-backdrop-filter で対応 |
MDN では backdrop-filter は「Baseline 2024(2024年9月から新しく広く利用可能)」と表示されています。Safari 18 で接頭辞なしに対応したことで、主要ブラウザがそろいました。Can I use のページでは、世界全体での対応率は 96.36% と表示されていました(いずれも2026年10月3日に各ページを開いて確認)。
では接頭辞はもう要らないのかというと、Safari 17 以前の利用者にも表示したいなら、まだ両方書いておくのが確実です。
.glass {
-webkit-backdrop-filter: blur(12px); /* Safari 17 以前のため */
backdrop-filter: blur(12px); /* 標準。こちらを後に書く */
}
なお、Chromium 141 で CSS.supports('-webkit-backdrop-filter', 'blur(1px)') を呼ぶと false、接頭辞なしは true が返りました。Chromium 系は接頭辞つきの書き方を受け付けないので、接頭辞つきだけを書くと Chrome や Edge で効かなくなります。必ず標準の書き方とセットにしてください。
| 対応させたい範囲 | 書き方 |
|---|---|
| 最新の主要ブラウザだけ | backdrop-filter のみ |
| Safari 17 以前も含める | -webkit-backdrop-filter と backdrop-filter の両方 |
| 効かない環境でも読めるようにする | @supports で背景色を濃くする(すりガラスのコード例を参照) |
Autoprefixer などのビルド時の道具を使っている場合は、対象ブラウザの設定に応じて接頭辞を自動で足してくれます。
描画負荷を抑える書き方
filter の中でも blur と drop-shadow、そして backdrop-filter は、周りの画素を広く読んで計算するため、色を変えるだけの関数より処理が多くなります。今回は描画時間の計測は行っていないので、一般に知られた性質と、負荷を抑える書き方を整理します。
| 気をつける点 | 理由 | 書き方の工夫 |
|---|---|---|
| ぼかし半径 | 半径が大きいほど読む画素が増える | 見た目が変わらない範囲で小さくする(8〜16px が目安) |
| かける面積 | 面積が広いほど計算が増える | 画面全体ではなく、ヘッダーやカードなど必要な範囲に絞る |
| 重ねる枚数 | backdrop-filter の要素が重なると、それぞれで計算が走る | すりガラスの要素を入れ子にしない |
| 後ろが動く場面 | スクロールや動画の上では毎フレーム計算し直す | 固定ヘッダーなど数を絞って使う |
| blur の値のアニメーション | 途中の値ごとに計算し直す | ぼかした画像を別に用意し、opacity で切り替える |
| 動きを控えたい利用者 | 設定で動きを減らしている人がいる | prefers-reduced-motion で transition を外す |
blur のアニメーションを opacity の切り替えに置き換える例です。
.thumb { position: relative; }
.thumb img { display: block; width: 100%; }
.thumb .blurred {
position: absolute; inset: 0;
filter: blur(8px);
opacity: 0;
transition: opacity 0.3s ease;
}
.thumb:hover .blurred { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
.thumb .blurred { transition: none; }
}
ぼかした層をあらかじめ描いておき、透明度だけを動かします。体感が重いと感じたら、開発者ツールのパフォーマンス計測で、filter を外したときとの差を比べてみてください。
filterとほかのプロパティの使い分け
似た結果を得られるプロパティが複数あるときの選び方です。
| やりたいこと | 向いている指定 | 補足 |
|---|---|---|
| 要素全体を半透明に | opacity プロパティ |
filter: opacity() と見た目は同じ。ほかの filter と並べたいときだけ関数を使う |
| 四角いカードに影 | box-shadow |
広がりや内側の影も指定できる |
| 切り抜き画像や吹き出しに影 | filter: drop-shadow() |
透明でない部分の形に沿う |
| 画像そのものをぼかす | filter: blur() |
端のにじみは親の overflow: hidden と拡大で整える |
| 後ろだけをぼかす | backdrop-filter: blur() |
背景を半透明にする |
| 写真の上の文字を読みやすく | filter: brightness() を画像に |
文字の要素にはかけない |
| 背景画像だけに効果 | 疑似要素に背景を置いて filter | 親にかけると中の文字にも効果がかかるため |
最後の行は、よく出会う場面です。背景画像を持つ要素に filter をかけると、中の文字も一緒にぼけます。背景を疑似要素に分けると、文字はそのまま保てます。
.hero { position: relative; overflow: hidden; color: #fff; }
.hero::before {
content: "";
position: absolute; inset: -20px;
background: url("photo.jpg") center / cover;
filter: blur(10px) brightness(0.7);
z-index: -1;
}
.hero { isolation: isolate; } /* 疑似要素が親の後ろへ抜けないようにする */
よくある質問
Q. filter: blur と backdrop-filter: blur はどちらを使えばよいですか? A. ぼかしたい対象で選びます。画像や要素そのものをぼかすなら filter、要素の後ろに見えているものをぼかして手前の文字を読ませたいなら backdrop-filter です。今回の計測でも、filter をパネルにかけたときは後ろの縞の色は変わらず、backdrop-filter のときだけ後ろの赤と青が混ざりました。
Q. backdrop-filter を指定したのに何も変わりません。
A. まず背景色が不透明になっていないかを確かめてください。不透明な白を指定した計測では、後ろの色は見えず真っ白になりました。rgb(255 255 255 / 0.6) のように透明度をつけると効果が見えます。次に、Safari 17 以前で見ている場合は -webkit-backdrop-filter を足します。
Q. -webkit-backdrop-filter はまだ書く必要がありますか? A. Safari 18 以降と、最新の Chrome・Edge・Firefox だけが対象なら不要です。Safari 17 以前にも表示したい場合は、接頭辞つきを先に、標準を後に、両方書きます。Chromium 141 は接頭辞つきの書き方を受け付けなかったので、接頭辞つきだけにするのは避けてください。
Q. grayscale(1) と saturate(0) は同じですか?
A. 今回の計測では、どちらも rgb(52, 152, 219) を rgb(136, 136, 136) に変え、同じ結果でした。意味の伝わりやすさで選んで構いません。白黒にしたいなら grayscale、彩度を少しずつ変えたいなら saturate が読みやすい書き方です。
まとめ
- filter は要素自身に、backdrop-filter は要素の後ろに効果をかけます。 使える関数は同じ10種類です。
- 値の範囲は3グループで覚えられます。0〜1のもの(grayscale・invert・opacity・sepia)、0以上で上限なしのもの(brightness・contrast・saturate・blur)、角度のもの(hue-rotate)です。
- 複数指定はスペース区切りで、左から順にかかります。
grayscale(1) sepia(1)はセピア色、sepia(1) grayscale(1)はグレーになりました。 - backdrop-filter は背景が半透明のときだけ見えます。 不透明な背景では後ろが塗りつぶされます。
- blur で端が白くにじむときは、親に overflow: hidden、子をぼかし半径の2倍ぶん広げると、端まで元の色に近づきます。
- Safari 17 以前も対象なら -webkit-backdrop-filter を標準の指定の前に併記します。Chromium 系は標準の書き方だけを受け付けます。
- filter をかけた要素は、子孫の position: fixed の基準になります。 固定要素の位置がずれたら祖先の filter を確かめます。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CSS filter一覧と使い方|blurとbackdrop-filterの違い」
株式会社RJCでは、CSSのfilterやbackdrop-filterのような表現の仕組みを仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。