
How to Create Wavy Boxes Using CSS
記事は上記記事を意訳したものです。
※当ブログでの翻訳記事は元サイト様に許可を得て掲載しています。
画像やコンテンツの装飾に使える、さらにクールな形状です。以下に示す2種類の形状について学んでいきます:
CSSを使用したウェーブボックス
通常通り、さまざまな形状のコードは私のオンラインコレクションで見つけることができますが、作成ロジックを理解するために一緒に見ていきましょう。

HTMLについては、私が作成するほとんどのCSS形状と同様に、単一の要素です。画像か:
<img src="" alt="">
またはテキストコンテンツ(もしくは任意のコンテンツ)を含む要素のいずれかです:
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi quam sem, tincidunt a enim sed, suscipit feugiat diam. Cras mollis ligula orci, a rhoncus dolor volutpat eget.</div>

最初のウェーブボックスの作成
右側の形状から始めます。これは「Wigglyボックス」とも呼んでいます。CSSマスクとグラデーションを使用します。CSS形状に関しては、もはや驚くことではないでしょう。clip-pathかグラデーションを使用したマスクのいずれかです。
結果は3つのシンプルなグラデーションのみで得られます。最初のグラデーションから始めましょう:

最初のグラデーションの概要
ボーダーエリアを空にするために、パディングエリアにクリップされた基本的な放射状グラデーションです。
.wiggly-box { --s: 30px; /* 波のサイズを制御 */ --w: 400px; /* 好ましい画像の幅 */ width: round(var(--w),4*var(--s)); aspect-ratio: 1; border: calc(2*var(--s)) solid #0000; box-sizing: border-box; mask: radial-gradient(var(--s),#0000 100%,#000) padding-box var(--s) var(--s)/calc(2*var(--s)) calc(2*var(--s)); }
ここまでは複雑なことは何もありません。変数--sを使用して、1つの値を調整するだけで形状を簡単に制御できるようにしています。これは最初のグラデーション(および他のグラデーション)のサイズ/寸法を制御し、また幅は4*Sの倍数である必要があります。
次に、内側の領域を埋める2番目のグラデーションを追加します。外側の曲線を残しながら、内側の円を埋めて次のようになります。

2番目のグラデーションの概要
周りに3*Sと等しいスペースを残す寸法で、中央に配置された単色のグラデーションを定義します。
.wiggly-box { /* 前と同じ */ mask: conic-gradient(#000 0 0) no-repeat 50%/calc(100% - 6*var(--s)) calc(100% - 6*var(--s)), radial-gradient(var(--s),#0000 100%,#000) padding-box var(--s) var(--s)/calc(2*var(--s)) calc(2*var(--s)); }
最後のグラデーションは、パズルを完成させる別の放射状グラデーションです!

3番目のグラデーションの概要
.wiggly-box { /* 前と同じ */ mask: radial-gradient(var(--s),#000 100%,#0000) 0 0/calc(4*var(--s)) calc(4*var(--s)), conic-gradient(#000 0 0) no-repeat 50%/calc(100% - 6*var(--s)) calc(100% - 6*var(--s)), radial-gradient(var(--s),#0000 100%,#000) padding-box var(--s) var(--s)/calc(2*var(--s)) calc(2*var(--s)); }
これを画像に適用すると、ファンシーな装飾が得られます。
グラデーションカラーを簡単に使用できることに注目してください。波が画像と重ならないようにするために、(既存のボーダーに加えて)パディングも追加しています。パディングに関して特別なロジックはありません。重なりを避けるために1*Sより大きければ良いだけです。
以下のように画像に丸い角を付けたい場合は、少し異なる実装を考えることができます:
最初の実装は丸い角では機能しません。なぜなら、半径が最初のグラデーションレイヤー(パディングエリアにクリップされたもの)に影響するからです。これを解決するために、同じ結果を得られる2つのレイヤーに置き換えます。

インターセクト合成の概要
パディングやボーダーを使用してグラデーションの領域をクリップする代わりに、別のグラデーションを考慮し、それらの間でインターセクト合成を実行します。言い換えれば、両方の可視部分のみを取ります。
img { mask: radial-gradient(var(--s),#000 100%,#0000) 0 0/calc(4*var(--s)) calc(4*var(--s)), conic-gradient(#000 0 0) no-repeat 50%/calc(100% - 6*var(--s)) calc(100% - 6*var(--s)), /* 新しいグラデーションレイヤー */ conic-gradient(#000 0 0) no-repeat 50%/calc(100% - 4*var(--s)) calc(100% - 4*var(--s)) intersect, /* 下のレイヤーとインターセクトする */ radial-gradient(var(--s),#0000 100%,#000) var(--s) var(--s)/calc(2*var(--s)) calc(2*var(--s)); }
これで2つの放射状グラデーションと2つの円錐グラデーションができました。円錐グラデーションはほぼ同じなので、繰り返しを避けるために変数を追加してコードを簡略化できます:
img { --_g:conic-gradient(#000 0 0) no-repeat 50%/; mask: radial-gradient(var(--s),#000 100%,#0000 calc(100% + 1px)) 0 0/calc(4*var(--s)) calc(4*var(--s)), var(--_g) calc(100% - 6*var(--s)) calc(100% - 6*var(--s)), var(--_g) calc(100% - 4*var(--s)) calc(100% - 4*var(--s)) intersect, radial-gradient(var(--s),#0000 calc(100% - 1px),#000) var(--s) var(--s)/calc(2*var(--s)) calc(2*var(--s)); }
2番目のウェーブボックスの作成
2番目のウェーブボックスも同じグラデーション構成に依存しています:2つの放射状グラデーションと1つの円錐グラデーションです。

最初の放射状グラデーションは外側の曲線を作成しますが、2番目のグラデーション(円錐グラデーション)で隠す内側の円も持ちます。そして、3番目のグラデーションがパズルを完成させます。

コードは以下のようになります:
.wavy-box { --s: 30px; /* 波のサイズを制御 */ --w: 400px; /* 好ましい幅 */ width: round(var(--w),4*var(--s)); aspect-ratio: 1; padding: var(--s); border: var(--s) solid #0000; box-sizing: border-box; mask: radial-gradient(calc(sqrt(2)*var(--s)),#000 100%,#0000), conic-gradient(#0000 0 0) content-box, radial-gradient(calc(sqrt(2)*var(--s)),#0000 100%,#000) var(--s) var(--s) padding-box; mask-size: calc(var(--s)*4) calc(var(--s)*4); }
今回は2つのグラデーションがクリップされています。放射状グラデーションは前の形状と同様にパディングエリアにクリップされ、円錐グラデーションはコンテンツエリアにクリップされます。
この実装でも、画像に丸い角を付けることができます。
しかし、形状を画像全体に適用したい場合は、パディングとボーダーを削除できる異なる実装に頼る必要があります。
4番目のグラデーションを導入し、前の形状で行ったのと同じインターセクト合成を実行します。小さな演習として、コードを一人で解析してみてください。
結論
ジグザグボックスと同様に、ウェーブ画像のギャラリーを示すデモで締めくくります!