ウェブ制作

サイト制作のちょっとしたティップスまとめ

ウェブ制作

公開日:2025/02/19

当サイトのリンクには広告が含まれています。

【CSS】mask-imageを活用した波線(ウェーブ)のコンテンツ区切り。画像1枚でどんな色にも対応

CSSのmask-imageを活用し、波線(ウェーブ)デザインのコンテンツ区切りを作る方法を解説。背景色やグラデーション、背景画像に関係なく、共通の1枚の画像で対応可能。汎用性を重視した実装方法を紹介します。

ウェブサイトの、コンテンツの境界線が波線・波模様(ウェーブ)のデザインの場合、どうコーディングするか迷います。

(例)コンテンツの区切りが直線ではなく、波線(ウェーブ型)のパターン

こういったデザインのコーディング方法について、今まではコンテンツと同じ色の波模様の画像を、透過PNGで用意していました。しかし、この方法では色の数だけ画像を用意する必要があり、デザイン変更の度に手間がかかります

そこで今回、一例として汎用性を重視したコードを考えてみました。コンテンツの色に関係なく、共通のSVG1枚だけの使い回しで対応できるよう、マスクを活用したCSSのデモコードを以下に提示します。

ここがポイント!

  • コンテンツの色を問わず使い回せる(色ごとの画像やCSSの追加不要)
  • 単色だけではなく、グラデーションや背景画像が設定されたコンテンツにも対応可能
  • CSSで制御するので、レスポンシブ対応等のメンテナンス性が高い

※CSSのmaskプロパティはローカルでは動かない(クロスドメインのブロック)ので、検証はサーバー環境下(もしくはバーチャルホスト)で行ってください。

デモ

section
section
section

HTML / CSS / 波画像 ※本筋に関係のないコードは省略

<section>section</section>

<section class="mask-image">section</section>

<section class="mask-image">section</section>
.mask-image {
    --height: 20px;
    mask-image:
        url(img/wave.svg),
        linear-gradient(to bottom, transparent 0%, transparent var(--height), #000 var(--height), #000 100%);
    mask-size: 240px;
    margin-top: calc(-1 * var(--height));
}

波画像:wave.svg サイズ:240px ✕ 20px(例)

準備するもの

波模様の画像

まず、マスク用の波模様の画像(※以下、波画像)を用意します。IllustratorFigmaなどを使って制作してください。

このサンプルは横方向に無限リピート出来るよう、両端をシンメトリーな形状で作りました。フォーマットはSVGです。

波画像:wave.svg サイズ:240px ✕ 20px(例)

※ここでは見やすいように背景色に黒を付けていますが、実際の背景データは透明です。

ちなみに、今回のコーディング方法なら、実はSVGではなく透過PNGでも目的は達成出来るのですが、せっかくならどんな高解像度ディスプレイにも対応できるベクター形式の強みを活かしたいので、特段の理由がなければSVGで良いと思います。

今回のデモで使う波画像

  • サイズ:240×20px ※横にリピートできるように両端のデザインを合わせる
  • フォーマット:SVG(または透過PNG)

CSS(マスク適用部分)

次に波画像のマスクを適用する部分のCSSです。

先ほど用意した240×20pxの波画像に対して、今回は以下のようなコードを構築しました。

.mask-image {
    --height: 20px;
    mask-image:
        url(img/wave.svg),
        linear-gradient(to bottom, transparent 0%, transparent var(--height), #000 var(--height), #000 100%);
    mask-size: 240px;
    margin-top: calc(-1 * var(--height));
}

デモコードの仕組みの解説

ここからは提示したデモコードの仕組みを1行ずつ解説していきます。

① まず波画像の高さを変数化する

--height: 20px;

まず波画像の高さの値は、この後で何回も使用するので、最初に変数化しちゃいます。これで複数回使用する際の修正を容易にします。

ちなみに「波画像の高さがそのままコンテンツの境界線の高さ」となります。

② mask-image を複数指定してマスクの重ね掛け

mask-image:url(img/wave.svg),linear-gradient(to bottom, transparent 0%, transparent var(--height), #000 var(--height), #000 100%);

ここからがややこしい。
このテクニックのポイントは、2つの異なるマスクカンマ区切りで組み合わせることです。

1つ目のマスク(波画像)

mask-image: url(img/wave.svg);

まず、波画像「wave.svg」をmask-imageに適用することで、コンテンツの背景が波模様にマスクされます。

波画像をマスクした状態

しかし、このままではそれ以外の部分も、全てマスク化されてしまうため、次のステップで調整します。

2つ目のマスク(グラデーションを使った透過処理)

linear-gradient(to bottom, transparent 0%, transparent var(--height), #000 var(--height), #000 100%);

次にlinear-gradientを使い、マスクの適用範囲を調整します。この linear-gradient の指定について1つずつ解説します。

linear-gradient(to bottom,
transparent 0%, transparent var(--height),
#000 var(--height), #000 100%
);

linear-gradientの中身(わかりやすいように改行)

to bottom

上から下方向にグラデーションを適用する。

transparent 0%, transparent var(--height)

開始位置(0%)からvar(--height)まではtransparent(透明)を指定します。結果、波画像の領域はマスクが適用されず何も影響を受けません(そのまま表示される)。

#000 var(--height), #000 100%

var(--height)から下の領域は #000(黒色)で塗りつぶします。

尚、一例として#000(黒色)にしましたが、#000という色自体に意味は無いので別に何色でも良いです。

mask-image は「透明度」に基づいてマスク処理を行うので、transparentか、それ以外か、ということが重要。

transparentの箇所にはマスクが適用されず、色を指定した箇所は完全にマスクされる領域になります。それにより波画像のvar(--height)から下の領域だけが完全に透明化されるということです。

mask-image:url(img/wave.svg),linear-gradient(to bottom, transparent 0%, transparent var(--height), #000 var(--height), #000 100%);

2つのマスクを設定した完成コード

③ mask-size で波画像のサイズを指定

mask-size: 240px;

mask-sizeを画像と同じサイズに指定することで、波画像が意図したサイズで繰り返し表示されます。

mask-repeatのデフォルト値はrepeatなので、特に指定せずとも横方向に無限にリピートされます。

補足

画像サイズを変更する場合は、--heightの値も合わせて調整

デモではmask-sizeの値は、画像のサイズと一致させたものの、ちゃんと縦横の比率が合っていれば、サイズは任意に変更可能です。画像がSVGならばベクター形式なので、レスポンシブ時に波のサイズを変えたい場合などに重宝します。

@media (max-width:750px) {
    .mask-image {
        --height: 10px;
        mask-size: 120px;
    }
}

例:レスポンシブ等でサイズ変更

④ 波画像の高さの分だけ、コンテンツを持ち上げて重ねることで、境界線が完成

margin-top: calc(-1 * var(--height));
ネガティブマージンで波の高さ分を持ち上げる

波模様が境界線に沿うように、波画像の高さ分だけネガティブマージンで上に持ち上げます。

これにより、コンテンツ同士が波画像の高さ分だけ重なり、コンテンツの境界線が完成します。コンテンツ側にはposition:relative;を指定し、階層関係(z-index)が正しく表示されるよう、必要に応じて調整してください。

⑤ (任意)波画像の高さの分だけ、paddingを指定する

padding-block: var(--height);

これはデザイン次第ですが、波画像の高さの分だけ、上下にpaddingを指定すれば、コンテンツの編集可能領域が明確になってわかりやすいです。まあ、これについてはお好みで。

完成デモ

section
section
section
<section>section</section>

<section class="mask-image">section</section>

<section class="mask-image">section</section>
.mask-image {
    --height: 20px;
    mask-image:
        url(img/wave.svg),
        linear-gradient(to bottom, transparent 0%, transparent var(--height), #000 var(--height), #000 100%);
    mask-size: 240px;
    margin-top: calc(-1 * var(--height));
}

まとめ

以上、SVG+CSSでmask-imageを活用した、コンテンツの区切りを波模様にするテクニックでした。

この方法を使えば、コンテンツの色、グラデーション、背景画像に関係なく、共通のSVG(またはPNG)を使ったclassを使い回すことが可能になります。

コンテンツの順番が入れ替わったり、追加されたりしても、いちいち波画像の追加やCSSの調整を加える必要はありません。そのまま同じclassで対応可能です。

参考にしてください。

上に戻る