結論 — マスクは「何で抜くか」で 3 種に分かれる
CSS のマスクは「何を基準に下のレイヤーを抜くか」で 3 種類に分かれます。透明度で抜く alpha マスク、明度で抜く luminance マスク、形で抜く vector マスク(CSS では clip-path)の 3 つです。どれを選ぶかは「半透明のフェードが要るか」「画像素材から抜くか」「幾何形状で切るか」のたった 3 問でほぼ決まります。
Figma のマスク機能(alpha / luminance / vector)も同じ 3 分類で、CSS 側のプロパティと素直に対応します。私はデザインデータを実装に落とすとき、この対応表を頭に入れておくだけで迷いが消えました。本稿は border-shape で UI の輪郭をデザインする の延長で、UI の輪郭を CSS でどう表現するかをマスクの観点から整理します。
alpha マスク — 不透明度でくり抜く既定の挙動
alpha マスクは、マスク画像の不透明度(alpha 値)をそのまま透け具合に使う方式です。mask-image でマスクを指定し、mask-mode: alpha(マスクを「透明度」と「明度」のどちらで解釈するかの切替の、透明度側)で動きます。
.target {
mask-image: url("mask.png");
mask-mode: alpha; /* 実は既定値なので省略できる */
mask-repeat: no-repeat;
mask-size: 100% 100%;
-webkit-mask-image: url("mask.png");
-webkit-mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
}
挙動は素直です。マスクの不透明な部分は下が見え、透明な部分は下が隠れ、半透明の部分は同じだけ半透明になります。透過 PNG や CSS グラデーション(linear-gradient(transparent, black) など)をマスクに使うと、端がふわっと消えるフェードが作れます。
落とし穴は 2 つあります。1 つはベンダープレフィックスで、Chrome と Safari は今も -webkit-mask-* を併記しないと効かない場面が残ります(2026 年 5 月時点)。もう 1 つは mask-mode の既定が alpha だという事実そのものです。私は luminance のつもりで真っ白な PNG を渡し、要素ごと消えた午後があります。白は不透明なら全部見えるはずが、その PNG の alpha がゼロだった、というだけのオチでした。
luminance マスク — 白黒の明度でくり抜く SVG 由来の発想
luminance マスクは、マスク画像の明るさ(luminance、輝度)で抜く方式です。mask-mode: luminance を指定すると、白い部分は見え、黒い部分は隠れ、グレーは明度に応じて半透明になります。
.target {
mask-image: url("luminance-mask.svg");
mask-mode: luminance;
-webkit-mask-image: url("luminance-mask.svg");
}
ここで効いてくるのが SVG との関係です。SVG の <mask> 要素は既定が luminance で、白黒のグラデーションで透け具合を描くのが伝統的な書き方でした。CSS の mask-mode: luminance はその発想を CSS に持ち込んだもの、と捉えると腹落ちします。Photoshop のレイヤーマスクで慣れた白黒の感覚も、こちらに近いです。
vector マスク — clip-path で形に沿ってくり抜く
幾何学的な形でスパッと切るなら、マスク画像ではなく clip-path(要素を指定した図形で切り抜くプロパティ)の出番です。円・多角形・SVG パスを指定して、その輪郭で要素を切り抜きます。
/* 円形 */
.avatar { clip-path: circle(50% at center); }
/* ひし形 */
.badge { clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); }
/* 自由形状(SVG パス) */
.blob { clip-path: path("M 0 0 L 100 0 L 100 100 L 0 100 Z"); }
clip-path は輪郭の内外を 0 か 1 で切るので、mask-image のような半透明のグラデーションは作れません。その代わり境界がくっきりします。自己交差する複雑なパスでは path(evenodd, "...") のように winding rule(塗りつぶし規則、自己交差した形の内外を判定するルール)を指定でき、Figma 側の NONZERO / EVENODD 設定をここに引き継ぎます。
つまずきやすいのは座標系です。SVG パスは左上原点で要素サイズと無関係な絶対座標、一方 circle() や polygon() は要素サイズに対する % で書けます。両者を混ぜると位置がずれます。私は最初 polygon() の座標を電卓で手計算していましたが、Clippy のような GUI ツールに切り替えたら 10 分の作業が 1 分で終わるようになりました。手計算していた頃の自分に教えてあげたい。
3 種の使い分け — 半透明・素材・形で決める
選択は 3 つの問いでほぼ決まります。半透明のフェードが要るか、画像素材から抜くか、幾何形状で切るか。次の表に落とし込みました。
| 観点 | alpha | luminance | vector (clip-path) |
|---|---|---|---|
| 抜く基準 | 不透明度 | 明度(輝度) | 図形の輪郭 |
| 半透明・フェード | 得意 | 得意 | 不可(0/1 で切る) |
| 主な入力 | 透過 PNG / グラデーション | 白黒画像 / SVG | 円・多角形・SVG パス |
| 境界 | なめらか | なめらか | くっきり |
| ブラウザ対応 | 広い | やや狭い | 広い |
| 由来の発想 | CSS の既定 | SVG <mask> | SVG <clipPath> |
判断の順番はこうしています。境界をぼかしたいなら alpha か luminance、素材が白黒なら luminance、透過 PNG やグラデーションなら alpha。輪郭をくっきり切りたいなら vector。そして複雑な自由形状で clip-path: path() のレンダリング負荷が気になったら、いっそ alpha マスク用の PNG に焼き込んでしまう、という逃げ道も持っておきます。色そのものの扱いは OKLCH 色空間でデザイナーが実務で詰まる 3 点 でも触れました。
実務でつまずいた落とし穴
最後に、3 種に共通して踏みやすい落とし穴をまとめます。結論だけ言えば「既定値」と「ブラウザ差」の 2 つに集約されます。
mask-size / mask-repeat / mask-position の既定値を意識していないと、マスクがタイル状に繰り返されたり、想定外の位置に出たりします。背景画像(background-*)と同じ感覚で、mask-repeat: no-repeat と mask-size を明示するのが安全です。mask ショートハンドでまとめて書く手もありますが、-webkit- 併記との相性で値が散らかりやすく、私は個別プロパティで書く方を選んでいます。
mask と border-radius、mask と transform: rotate() の組み合わせは、Chrome と Safari で結果が割れます。回転とマスクを併用するときは、要素とマスクの座標系が同じ基準で回っているかを必ず実機で確認します。Figma のデータを自動変換するときは、relativeTransform から相対位置と回転を取り出し、入れ子マスクは階層ごとに独立した div でラップする素朴な再帰が、結局いちばん壊れませんでした。native な要素の使い分けは dialog / Popover / details をデザイナーの目で使い分ける も併せてどうぞ。
まとめ
CSS のマスクは alpha / luminance / vector の 3 種で、それぞれ「不透明度・明度・形」のどれで抜くかが違います。半透明が要るなら alpha か luminance、白黒素材なら luminance、くっきり切るなら clip-path の vector。Figma の 3 マスクともそのまま対応するので、デザインデータを実装に落とすときの共通言語として使えます。困ったら、何で抜きたいのかを 1 つ決める。そこから逆算すれば、プロパティは自然に 1 つへ絞れます。
Tags
よくある質問
- mask-image と clip-path はどう使い分けますか?
- 半透明のフェードや画像素材から抜きたいときは mask-image(alpha / luminance)、円や多角形など輪郭をくっきり切りたいときは clip-path(vector)を使います。clip-path は内外を 0/1 で切るので半透明グラデーションは作れません。
- mask-mode の alpha と luminance の違いは?
- alpha はマスク画像の不透明度で抜き、luminance は明度(白=見える / 黒=隠れる)で抜きます。CSS の既定は alpha、SVG の mask 要素 由来の発想が luminance です。luminance は古い Safari で対応が弱い点に注意します。
- なぜ -webkit-mask- を併記するのですか?
- Chrome と Safari では 2026 年時点でも -webkit-mask-* のプレフィックスを併記しないと効かない場面が残るためです。mask-image / mask-repeat / mask-size などは webkit 版もあわせて書くのが安全です。
- Figma のマスクは CSS にそのまま対応しますか?
- 対応します。Figma の alpha mask は mask-mode: alpha、luminance mask は mask-mode: luminance、vector mask は clip-path に素直に写せます。vector では winding rule(NONZERO / EVENODD)と座標系の引き継ぎに注意が必要です。