「ボタンのグラデーションをホバーでふわっと色変えしたい」
そう思って transition を設定したのに、全然動かなくて困ったことはありませんか?
実は、CSSの background-image(グラデーション)は、そのままではアニメーションさせることができません。
でも大丈夫です!いくつかのアプローチを使えば、実装可能です。
今回は、「実務で使える定番の2パターン」と、「最新のCSS機能(@property)を使ったパターン」の合計3つの方法を解説します。
目次
1. background-sizeとpositionで動かす(定番)
一番よく使われる、互換性の高い方法です。
グラデーションの色そのものを変化させるのではなく、「背景サイズを大きくして、表示位置をズラす」ことで、色が変化したように見せます。
実装のポイント
background-sizeを 200% など大きめに設定する- ホバー時に
background-positionを移動させる
実際の挙動はこちらです。
See the Pen
Untitled by 広瀬和哉 (@lpvcfdes-the-styleful)
on CodePen.
メリット・デメリット
この方法は、厳密には「色Aから色Bへ変化」しているわけではなく、「隠れていた色が出てくる」だけです。
そのため、「赤から青へじわっと変える」といった完全な色変化は苦手ですが、キラッと光るような演出には最適です。
2. 疑似要素(::before)を重ねてフェードさせる
「どうしても色Aから色Bへ、クロスフェードさせたい!」という場合は、疑似要素を使います。
2枚のレイヤーを重ねて、上のレイヤーの透明度(opacity)を変えるアプローチです。
実装のポイント
- 元の要素に「変更前のグラデーション」を指定
::beforeなどの疑似要素で「変更後のグラデーション」を上に重ねる- 疑似要素の
opacityを 0 から 1 にアニメーションさせる
実際の挙動はこちらです。
See the Pen
Untitled by 広瀬和哉 (@lpvcfdes-the-styleful)
on CodePen.
メリット・デメリット
見た目は非常に綺麗で滑らかですが、DOM構造が少し複雑になります。
また、疑似要素を装飾のために使い切ってしまうため、他のデザイン(アイコンなど)で疑似要素を使いたい時に競合しないよう注意が必要です。
3. 【最新】@property で色そのものを変化させる
最後に紹介するのが、今一番ホットなCSS Houdini API の @property を使った方法です。
これを使うと、ブラウザに「これは色(color)だよ」と教えてあげることで、今まで不可能だったグラデーションの中身のアニメーションが可能になります。
実装のポイント
- CSS内で
@propertyを定義し、syntax: '<color>'を指定する - グラデーションの色指定に、定義した変数(カスタムプロパティ)を使う
- ホバー時に変数の色コードを書き換える
実際の挙動はこちらです。非常にコードがスッキリしているのが分かります。
See the Pen
Untitled by 広瀬和哉 (@lpvcfdes-the-styleful)
on CodePen.
サンプルコード解説
CSS側で、変数の「型」を定義するのが最大のミソです。
/* カスタムプロパティの定義 */
@property --grad-color-1 {
syntax: '<color>'; /* ブラウザに「これは色だよ」と教える */
initial-value: #3b82f6;
inherits: false;
}
@property --grad-color-2 {
syntax: '<color>';
initial-value: #8b5cf6;
inherits: false;
}
.button {
background: linear-gradient(90deg, var(--grad-color-1), var(--grad-color-2));
transition: --grad-color-1 0.5s, --grad-color-2 0.5s; /* 変数に対してtransitionをかける */
}
.button:hover {
--grad-color-1: #f59e0b;
--grad-color-2: #ef4444;
}
メリット・デメリット
JavaScriptを使わずにCSSだけで完結し、擬似要素も汚さないため、最もスマートな設計です。
主要ブラウザでのサポートも進んでいますが、非常に古いブラウザを対象とする案件では注意が必要です。
まとめ:案件に合わせて使い分けよう
今回紹介した3つの方法は、それぞれ適したシチュエーションが異なります。
- background-size: 互換性重視、キラッとさせたい時
- 疑似要素: 古いブラウザ対応が必要だが、確実に色を変えたい時
- @property: モダンブラウザ対応OKで、コードを綺麗に保ちたい時
特に @property は、角度(angle)のアニメーションなど応用範囲が広いので、ぜひ今のうちにマスターしておきましょう!
