ウェブ制作

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

ウェブ制作

公開日:2025/07/01

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

【CSS】背景グラデーション(linear-gradient)にアニメーションを効かせる2つの方法:疑似要素/@property

linear-gradientにtransition は効かない?CSSだけで背景グラデーション(linear-gradient)の色を滑らかに変化させる2つの方法(疑似要素 / @property)を紹介します。

一見シンプルに見えるけれど、いざ実装しようとすると手間がかかったり、ちょっとした知識が必要だったりする。

そんなウェブ制作の「現場あるある」とその対処法を紹介していくシリーズ。

今回のテーマは、「背景がグラデーション(linear-gradient)の要素を、ホバー時にアニメーションさせる方法」です。

完成デモ1:疑似要素::beforeの利用

完成デモ2:カスタムプロパティ (@property) を利用

linear-gradienttransition は効かない

現場でよくあるのが、背景色がグラデーションになっている「ボタン」のホバーエフェクト

指示書には「ホバーした時、背景の色はフワッと変化させてください!」みたいなメモが気軽にあるんだけど、実はCSSのlinear-gradienttransitionプロパティは効かない。。

そのため、transition効いているように「見せる」ために、CSSに一工夫加える必要があります。

主な手法としては、「疑似要素を利用する方法」と、「CSSカスタムプロパティ (@property) を活用する方法」が考えられます。

解決策1:疑似要素の opacity を切り替える

一般的なテクニックです。

ボタンに ::before::after の疑似要素を追加し、背景全体を覆うように配置します。

通常時は opacity: 0、ホバー時に opacity: 1 へアニメーションさせることで、あたかも linear-gradient の背景色が滑らかに変化したかのように見せかけます。

デモ

HTML

<button>ボタン</button>

CSS ※要点のみ抜粋

button {
    position: relative;
    background: linear-gradient(90deg, #53C1FD, #3274E2);
    overflow: hidden;
    z-index: 1;

    /* ホバー時用の背景色(非表示状態) */
    &::before {
        content: "";
        opacity: 0;
        position: absolute;
        inset: 0;
        background: #2759AD;
        transition: opacity .3s;
        z-index: -1;
    }

    /* ホバーで表示 */
    @media (any-hover: hover) {
        &:hover::before {
            opacity: 1;
        }
    }
}

補足

HTMLのデモはスマホでも効果が確認出来るよう@media (any-hover: hover){}指定をあえて解除しています。

アイコン付きボタンへの応用

ボタンデザインには、アイコンが含まれることも多いと思います。

アイコンも、CSSの疑似要素で実装されていることが多いため、ボタン本体の::before / ::after既にアイコンに使われている事も多いです。

このような場合は、ボタン内のテキスト部分をspan等のタグで囲み、その要素に対して疑似要素を使えば干渉せずに実装可能です。

HTML

<button><span>ボタン</span></button>

CSS ※要点のみ抜粋

button {
    position: relative;
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 1em;
    background: linear-gradient(90deg, #53C1FD, #3274E2);
    overflow: hidden;
    z-index: 1;

    /* アイコンの反対側に同サイズの余白を生成(Gridの活用) */
    &::before {
        content: "";
    }

    /* アイコン */
    &::after {
        content: "";
        display: block;
        justify-self: end;
        width: .8em;
        aspect-ratio: 1/1;
        mask: url(/img/ico_arrow.png) center center / contain no-repeat;
        background-color: #fff;
    }

    /* ホバー時用の背景色(非表示状態) */
    &>span::before {
        content: "";
        opacity: 0;
        position: absolute;
        inset: 0;
        background: #2759AD;
        transition: opacity .3s;
        z-index: -1;
    }

    /* ホバーで表示 */
    @media (any-hover: hover) {
        &:hover>span::before {
            opacity: 1;
        }
    }
}

解決策2:CSSカスタムプロパティ (@property) を使う

比較的新しい方法として、CSSの @property ルールを使ったアプローチがあります。こっちのほうがコードの記述量は抑えられてシンプルです。また見せかけではなく、ちゃんとtransitionが効きます。

方法としては、アニメーションさせたい色をカスタムプロパティとして定義し、ホバー時にその値を変更することで、グラデーションの色が transition によって滑らかに変化します。

デモ

CSS カスタムプロパティ

@property --custom-color-1 {
    syntax: "<color>";
    inherits: false;
    initial-value: #53C1FD;
}

@property --custom-color-2 {
    syntax: "<color>";
    inherits: false;
    initial-value: #3274E2;
}

CSS ※要点のみ抜粋

.button {
    box-sizing: border-box;
    background: linear-gradient(90deg, var(--custom-color-1), var(--custom-color-2));
    transition: --custom-color-1 .3s, --custom-color-2 .3s;

    /* ホバーで背景色を変更 */
    @media (any-hover: hover) {
        &:hover {
            --custom-color-1: #2759AD;
            --custom-color-2: #2759AD;
        }
    }
}

通常のCSS変数ではダメみたい

仕組みだけ一見すると、@property を使わずに通常のCSS変数(例:–custom-color-3、–custom-color-4;)でも実現できそうに思えますが、実際には色の変化がアニメーションせず、一瞬で切り替わってしまいました。

※ダメな事例:CSS変数の利用

button {
    --custom-color-3: #53C1FD;
    --custom-color-4: #3274E2;
    background: linear-gradient(90deg, var(--custom-color-3), var(--custom-color-4));
    transition: --custom-color-3 .3s, --custom-color-4 .3s;

    @media (any-hover: hover) {
        &:hover {
            --custom-color-3: #2759AD;
            --custom-color-4: #2759AD;
        }
    }
}

調べたところ、通常のCSS変数の定義は、ただの「文字列」なので、ブラウザはその値をアニメーションすることができないようです。

一方で、@property で定義したカスタムプロパティは、単なる文字列ではなく「型情報」を持ちます。
今回の場合、 型のプロパティとしてcolorを明示的に定義しているため、ブラウザは、その値が「色」であることを認識出来き、中間色を計算して、transition に従ってアニメーションしてくれる……と解釈したが合ってるかな?

参照

まとめ

以上、「CSSグラデーション(linear-gradient)の色をアニメーションで変化させる方法」でした。

linear-gradient の背景色をホバーでアニメーションさせるには、少し工夫が必要です。

疑似要素の opacity を利用する方法は、古くから使われているメジャーな手法で、安定した動作が期待できます。

@property を利用する方法は、より宣言的で、コードもスッキリしますが、比較的新しい機能のため、ブラウザの対応状況に注意が必要です。といっても2025年現在、主要なブラウザでは対応済みなのでそこまで心配はいりません。

プロジェクトの要件や対象ブラウザに応じて、適切な方法を選択してください。

上に戻る