CSS でグラデーションの枠線を表現する方法としてよく挙げられるのが、border-image-source
でグラデーションを指定した以下のようなコードです。
.border{ display: inline-block; padding: 20px; /* 4px幅のボーダー */ border: 4px solid blue; /* ボーダー領域の画像ソース(linear-gradient でグラデーションで表示) */ border-image-source: linear-gradient( 135deg, blue, green ); /* ボーダー領域の画像の分割数(グラデーションとボーダーを合わせる) */ border-image-slice: 1; }
しかし、border-image-source
を利用した場合、border-radius
を指定してもボーダーが角丸になりません。
角丸ボーダーでグラデーションを表現する方法としてよく見かけるものは、div 等で要素をラップしたり疑似要素(::before
, ::after
)を利用してラッパー要素を background-image
でグラデーション背景にして、ラッパー要素より中心に縮小したインナー要素は background-color
で表示エリアの背景色と同じ色で塗りつぶしてラッパーとインナーの差分でグラデーションボーダーを表現するというもの。
ただし、この方法ではグラデーションボーダー要素が表示されるコンテンツエリア内の背景が単色でない場合や、背景画像を表示しているような場合は、ボーダー内の背景色が視覚的に浮いてしまい、汎用性は全くありません。
そこで、ここではページの背景状態(背景色、グラデーション、背景画像)に依存せず、要素の内部背景は透過して角丸のアウトライン(枠線)のみがグラデーションで表示される汎用性の高い CSS を考えてみます。
See the Pen Untitled by digistate (@digistate) on CodePen.
background プロパティ
まず、疑似要素に background-image
でグラデーション(linear-gradient
)で塗りつぶします。
ボーダーの太さは疑似要素に対して直接 border
プロパティで指定します(ボーダーカラーは透過)。
border: 4px solid transparent; /* ボーダーカラーは透過(transparent) */
上記で指定したボーダーの領域も含めてグラデーションで塗りつぶすため、background-image
で指定したグラデーション背景を適用する基準位置(background-origin
)と範囲(background-clip
)に border-box
を指定します。
background-image: linear-gradient(135deg, blue, green); /* グラデーション背景 */ background-origin: border-box; /* 背景の基準位置はボーダーも含める */ background-clip: border-box; /* 背景の適用範囲はボーダーも含める */
これらを background
プロパティのみ(ショートハンド)でまとめて指定した場合は以下のようになります。
background: linear-gradient(135deg, blue, green) border-box border-box;
mask プロパティ
続いて mask
プロパティを利用してマスクレイヤーを表示し、ボーダーの太さ(border-width
)より内側を切り抜くことでグラデーションボーダーを表現します。
具体的には、マスクレイヤーは mask-image
プロパティで linear-gradient
にてベタ塗りのレイヤーとして2つ定義します。
そして mask-clip
プロパティにて2つのレイヤーの描画領域について、1つ目はボーダーより内側の境界まで(padding-box
)とし、2つ目はボーダー領域を含めた要素全体の外周まで(border-box
)を定義します。
最後に、レイヤーの合成方法を定義する mask-composite
プロパティに exclude
を指定することで、2つのレイヤーの重なっていない部分(ボーダー領域)を描画領域の対象として合成します。
Chromium 系のブラウザは exclude ではなく destination-out をベンダープレフィックス付きで指定します。-webkit-mask-composite: destination-out
// Chromium -webkit-mask-image: linear-gradient(#fff 0 0), linear-gradient(#fff 0 0); /* 2つのマスクレイヤー */ -webkit-mask-clip: padding-box, border-box; /* レイヤーごとの描画領域の範囲 */ -webkit-mask-composite: destination-out; /* レイヤーが重なっていない領域を描画対象 */ // FireFox mask-image: linear-gradient(#fff 0 0), linear-gradient(#fff 0 0); mask-clip: padding-box, border-box; mask-composite: exclude;
ショートハンドでまとめた場合は以下のようになります。
-webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0) border-box; -webkit-mask-composite: destination-out; mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0) border-box; mask-composite: exclude;
先述の background
プロパティとこの mask
プロパティを組み合わせることで内部を透過した状態で角丸のグラデーションボーダーを表現できます。
.button{ position:relative; display:inline-block; padding:24px 28px; } .button::before{ content: ""; position: absolute; top: 0; left: 0; right: 0; bottom: 0; border-radius: 50px; border: 5px solid transparent; background: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%) border-box border-box; -webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0) border-box; -webkit-mask-composite: destination-out; mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0) border-box; mask-composite: exclude; }