border-shape は border-radius の続編ではない
border-shape は「角を丸くする」のではなく、要素の輪郭そのものを任意形状で描き直すプロパティです。border-radius の拡張ではなく、別の層として加わる新しい仕組みと捉えるのが素直でした。
W3C の CSS Borders and Box Decorations Module Level 4(草案)で議論されている案で、現状は Working Draft の段階です。Chrome 147 と Edge 147 で実験的に実装が始まりました。Safari と Firefox は未対応です。本番投入はまだ先ですが、輪郭の語彙が増える兆しとして観察しておきたい段階に入りました。
私が border-radius で困っていたのは「角を丸くする以上のことができない」点でした。誌面デザインで「ノッチ付きカード」や「斜め切りのチップ」を作りたい時、結局 clip-path(要素の切り抜き)に逃げるしかない。border-shape はその「逃げ場」に正面の入口を開けた形になります。
clip-path との違いは、影と境界線が生きるかどうか
clip-path は要素を「切り抜く」、border-shape は要素を「縁取る」。違いはこの 1 行ですが、結果は大きく分かれます。border / box-shadow / outline が形に追従するかどうかが決定的な分岐点です。
clip-path で五角形にした要素には、box-shadow が効きません。影は元の矩形に対して落ち、切り抜かれた途端に消えます。outline も同じ理由で形に追従しない。これは「切り抜き」なのだから当然なのですが、UI で輪郭装飾を試みると毎回ぶつかる壁でした。
border-shape は要素の幾何そのものを差し替えるため、影も罫線も新しい形に沿って描かれます。box-shadow: 0 2px 8px rgba(0,0,0,0.1) がノッチ付きカードのノッチ部分まで含めて落ちます。これは派手な機能ではないのですが、デザインの整合性を保つ上で地味に重要な差です。
design token としての扱い方
shape は radius と同じ階層で design token 化できます。命名規則は radius の流儀をそのまま流用すれば素直に収まりました。
@theme {
--shape-card-engineering: path('M 0 12 L 12 0 L calc(100% - 12px) 0 L 100% 12 L 100% 100% L 0 100% Z');
--shape-card-design: path('M 0 0 L 100% 0 L 100% 100% L 0 100% Z');
--shape-chip: path('M 8 0 L calc(100% - 8px) 0 L 100% 50% L calc(100% - 8px) 100% L 8 100% L 0 50% Z');
}
私の場合、5 部門のうち Engineering と AI だけに専用 shape を割り当てました。全部門に shape を配ると誌面がうるさくなります。形を持つ部門と持たない部門を分けたほうが、部門コードとして強く立ちます。
token 名の階層は radius / shape / outline で 3 段に分け、role token(--shape-hero --shape-chip)を間に挟みました。component class からは border-shape: var(--shape-hero) で参照するだけ。design-system-record-b-plus-a-hybrid で書いた 4 階層トークン構成と同じ流儀で、shape だけ別パスを切る形にはしませんでした。
スケールは 3 段にしました。--shape-soft(角を 4px だけ斜めに切る)、--shape-strong(12px のノッチ)、--shape-signature(部門固有の独自形状)の 3 段です。半径と同様、スケールが多すぎると現場で迷うため、xs / sm / md / lg / xl のような細分化はしないと決めました。実際に必要なのは「ほぼ気付かない」「ちゃんと気付く」「部門の顔」の 3 段で足ります。
私が試した手順と、最初に失敗したこと
実装は Chrome 147 のフラグ付き機能から試しました。CSS の値として path() polygon() circle() を受け取れますが、最初は path() の座標系で派手にハマりました。
最初に書いたのはこの値です。
border-shape: path('M 0 0 L 100 0 L 100 100 L 0 100 Z');
座標を絶対値の px で書いてしまい、要素サイズが変わると形が崩れる。% と calc() を混ぜて相対化したら直りました。地味に時間がかかった部分で、座標を書きながら「これは Tailwind のユーティリティクラスで扱える粒度の話ではないな」と気付きました。
@property で path 値を登録すれば transition も効きますが、Chrome 147 時点では shape 値の補間がギクシャクします。アニメーションは当面諦めて、static な装飾として使うのが安全でした。
いつ使うかは、誌面の必然性に従う
border-shape は装飾のためではなく、用途のために使うのが正解だと考えています。「形を変えられるから変える」は誌面を散らかします。
AetherEchoes の場合、Engineering 部門のカードに「右上ノッチ」を入れました。理由は 2 つあります。1 つはコード片を貼った時の角度感と整合させるため。もう 1 つは部門識別を「色 + 形」の 2 軸にすると、色覚特性がある読者にも識別しやすくなるためです。
逆に Essay 部門には shape を使いません。文章だけのページに過剰な形は邪魔になります。Design 部門のヒーローは「内向きの円弧」を試しましたが、最終的に外しました。形が読者の視線を内側に引き込みすぎて、本文に集中できなくなるためです。形は強い装置で、弱い場所に置くと効きすぎます。
まとめ
border-shape は border-radius の続きではなく、UI の語彙を 1 段増やすプロパティです。Chrome 147 で実装が始まったばかりで、本番投入は時期尚早。それでも token 設計の側で「shape」枠を空けておくと、ブラウザ実装が出揃った時にすぐ反応できます。
私の自宅の MacBook Air M2 の Chrome は、path 値を間違えた拍子に 1 回クラッシュしました。たぶん私の記法が悪かったのでしょう。実装初期の機能を触る時は、ブラウザを再起動する覚悟も含めて楽しむのがちょうど良い距離感だと思います。
Tags
よくある質問
- border-shape と border-radius は何が違いますか?
- border-radius は角を丸くするプロパティです。border-shape は要素の輪郭そのものを任意形状(path / polygon / circle)で描き直すプロパティで、別の層として加わる新しい仕組みです。border-radius を置き換えるものではなく、共存します。
- clip-path と何が違いますか?
- clip-path は要素を「切り抜く」ため、box-shadow や outline が形に追従しません。border-shape は要素の幾何そのものを差し替えるため、影も罫線も新しい形に沿って描かれます。装飾の整合性を保つ用途では border-shape のほうが扱いやすくなります。
- 本番投入できますか?
- 2026 年 5 月時点では Chrome 147 と Edge 147 の実装のみで、Safari と Firefox は未対応です。W3C も Working Draft 段階のため、本番投入はまだ時期尚早です。design token の枠だけ空けておき、実装が出揃った時に反応する準備が現実的です。
- design token としてどう扱えばよいですか?
- radius と同じ階層で扱えます。命名規則は radius の流儀(--shape-card, --shape-chip など)をそのまま流用できます。role token を間に挟み、component class からは border-shape: var(--shape-hero) の形で参照する構成が素直に収まりました。