mask-imageで簡単反転ボタン

掲載日
更新日

はじめに

クリックすると、背景とアイコンの色が反転するボタンの動作イメージGIF動画

業務で添付GIF画像のような背景は白、アイコンはオレンジのボタンがあり、ボタンをクリックすると背景オレンジ、アイコンは白という風に反転させるボタンを作りたい場面がありました。

最初はsvgをPHPのfile_get_contentsなどを使ってHTMLに直接に埋め込み、fillとかstrokeを使って頑張って反転させていたのですが、IE非対応でよければmask-imageというCSSプロパティを使えば簡単にできることが分かりました。

svgを使ってやる場合 

svgを使う場合、imgタグで読み込むとcssのfillやstrokeでは色付けできません
なので、反転後の色のタグを用意しておいてクリックで画像を切り替えるか、HTMLに直接svgタグ形式で埋め込んでfillやstrokeで色付けが必要です。
以下のような実装になります。

<html>

<body>
    <div class="svg-pattern">
        <button type="button" class="button svg-pattern-button ">
            <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#000000">
                <path
                    d="M240-80v-366q-54-14-87-57t-33-97v-280h80v240h40v-240h80v240h40v-240h80v280q0 54-33 97t-87 57v366h-80Zm400 0v-381q-54-18-87-75.5T520-667q0-89 47-151t113-62q66 0 113 62.5T840-666q0 73-33 130t-87 75v381h-80Z" />
            </svg>
            Food
        </button>
    </div>
</body>

<style>
    .button {
        border: 2px solid oklch(76.9% 0.188 70.08);
        background-color: #fff;
        border-radius: 50%;
        width: 80px;
        height: 80px;
        padding: 10px;
        margin: 0;
    }

    .button:hover {
        background-color: oklch(98% 0.016 73.684);
    }

    .button.active {
        background-color: oklch(76.9% 0.188 70.08);
        color: #fff;
    }

    .svg-pattern-button svg {
        fill: oklch(76.9% 0.188 70.08);
    }

    .svg-pattern-button.active svg {
        fill: #fff;
    }
</style>

<script>
    const svgPatternButton = document.querySelector('.button');
    svgPatternButton.addEventListener('click', () => {
        if (svgPatternButton.classList.contains('active')) {
            svgPatternButton.classList.remove('active');
        } else {
            svgPatternButton.classList.add('active');
        }
    });
</script>

</html>

直接svg書き込める場合は良いんですが、自分の場合別の管理画面でsvgの画像をアップロードして、それを読み込む必要がありました。
業務ではPHPを使用しているのでfile_get_contentsを使用してsvg画像のパスを読み込み、埋め込みをする…ということをすればよかったんですが、
更なる課題として、GoogleMapに特定条件で埋め込んだピンにアイコンを表示して、さらにそのピンがクリックされたら反転…ということも必要になりました。

そうすると今度はjavascript側でajaxで読み込んで…?という話になってきてアイコンの色の反転程度でやたらと工数がとられる話になってきてしまい、そこで見つけたのがmask-imageでした。

mask-imageでいい感じにする

mask-imageは適用された画像をもとにマスクする(非表示にする)というのが大本の機能のようですが、
そのマスクした位置の背景色を変えることでアイコンの色を変えるような動きをさせることが可能になっているようです。
以下のようなHTMLファイルを保存して開くと、最初に添付したGIF画像のような動作を見ることができます。

※事前にsvg画像はhtmlと同じ階層にfood.svgという名前で用意しておいてください。

<html>

<body>
    <strong>クリックで色を反転させる</strong>
    <div class="mask-pattern">
        <button type="button" class="button mask-pattern-button ">
            <div></div>
            Food
        </button>
    </div>
</body>

<style>
    .button {
        border: 2px solid oklch(76.9% 0.188 70.08);
        background-color: #fff;
        border-radius: 50%;
        width: 80px;
        height: 80px;
        padding: 10px;
        margin: 0;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: space-evenly;
    }

    .button:hover {
        background-color: oklch(98% 0.016 73.684);
    }

    .button.active {
        background-color: oklch(76.9% 0.188 70.08);
        color: #fff;
    }

    .mask-image-button {
        width: 80px;
        height: 80px;
    }

    .mask-pattern-button div {
        mask-image: url("./food.svg");
        width: 24px;
        height: 24px;
        background-color: oklch(76.9% 0.188 70.08);
    }

    .mask-pattern-button.active div {
        background-color: #fff;
    }
</style>

<script>
    const svgPatternButton = document.querySelector('.button');
    svgPatternButton.addEventListener('click', () => {
        if (svgPatternButton.classList.contains('active')) {
            svgPatternButton.classList.remove('active');
        } else {
            svgPatternButton.classList.add('active');
        }
    });
</script>

</html>

mask-imageの更に優れている点として、今回は大本のネタがsvg画像を使っていますが、png画像などでも適切に背景の透過がされていれば同じことが可能です。

今回自分が業務で必要だったのも、「別の管理画面でアイコン画像をアップロードしてそれを使用する」という操作が必要で、この際fillやstrokeで色を付けたかった都合で画像の種類をsvgに縛っていましたが、mask-imageを使うのであればsvgの縛りは不要になります。

「アイコンに使っていいのはsvg画像のみです。」と言ってすんなり通じるお客様ばかりではないので、広く利用されてる画像形式が通用するのはかなりありがたいです。

関連リンク

 
記事の作成者のA.W.のアイコン

この記事を書いた人

A.W.
茨城県在住Webエンジニアです。 PHPなどを業務で使用しています。 趣味ではGoやNuxt、Flutterをやってます。

Comment