【GSAP】プロパティに書くだけ!?CSS変数を活用した擬似要素アニメーション

Webアニメーションの実装に欠かせない GSAP(GreenSock Animation Platform)。 クラスや要素を指定してサクッとリッチな動きを作れるのが魅力ですが、「::before や ::after などの擬似要素をGSAPで動かしたい!」と思った時、どうやって指定すればいいか迷ったことはありませんか?

擬似要素はDOM上に存在しないため、直接 gsap.to('.target::before', {...}) のように指定することはできません。 そこで活躍するのが「CSS変数(カスタムプロパティ)」です!

▶︎関連記事:JSでのCSS変数操作

GSAPは、CSS変数の値も普通のプロパティと同じように、アニメーションさせながら書き換えることができます。今回は、この強力な機能を活用して、ボタンホバー時にフワッと広がる波紋(パルス)アニメーションを作ってみましょう!

デモ動作

See the Pen GSAP × CSS変数で擬似要素をアニメーション by mikanbako (@mikanbako) on CodePen.

全画面でのデモ動作は以下のリンクからご確認下さい!(別タブで開かれます)

実装コード紹介

【HTML】

<div class="l-wrap">
  <h2>GSAP × CSS変数 アニメーションデモ</h2>
  <p class="p-desc">ボタンにホバーしてみてください!<br>擬似要素がGSAPでアニメーションします。</p>
  
  <div class="p-demo-box">
    <!-- このボタンの擬似要素(::before)をGSAPで動かします -->
    <button class="c-ripple-btn js-gsap-btn">Hover Me!</button>
  </div>
</div>

【CSS】

.l-wrap { 
  padding: 40px 20px;
  max-width: 600px;
  margin: 0 auto;
  color: #3e3e3e;
  text-align: center;
}
h2 { 
  font-size: 16px;
  color: #1bb4d4;
  margin-bottom: 16px;
}
.p-desc { 
  font-size: 16px;
  font-weight: bold;
  color: #666;
  line-height: 1.6;
  margin-bottom: 32px;
}
.p-demo-box { 
  padding: 40px 0;
}

/* =========================================
   ボタンと擬似要素
========================================= */

.c-ripple-btn {
  position: relative;
  padding: 16px 48px;
  font-size: 18px;
  font-weight: bold;
  color: #fff;
  background-color: #1bb4d4;
  border-radius: 30px;
  cursor: pointer;
  z-index: 1;

  /* 💡ポイント1: GSAPで操作するためのCSS変数を初期定義! */
  --ripple-scale: 1;
  --ripple-opacity: 0.8;
}

/* 擬似要素(::before)で作る波紋のベース */
.c-ripple-btn::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 30px;
  background-color: #1bb4d4;
  z-index: -1;
  pointer-events: none;
  
  /* 💡ポイント2: CSS変数を割り当てる(※CSSのtransitionは書きません!) */
  transform: scale(var(--ripple-scale));
  opacity: var(--ripple-opacity);
}

【JavaScript】

// 対象のボタンを取得
const btn = document.querySelector('.js-gsap-btn');

// 💡ポイント3: マウスホバー時のアニメーション
btn.addEventListener('mouseenter', () => {
  gsap.fromTo(btn, {
    // CSS変数名(文字列)をそのままプロパティに指定するだけ!
    '--ripple-scale': 1,
    '--ripple-opacity': 0.8,
  }, {
    '--ripple-scale': 1.5, // 1.5倍まで拡大
    '--ripple-opacity': 0, // 同時に透明にする
    duration: 0.6,
    ease: 'power2.out'
  });
});

コードの解説・仕組み

CSS変数は gsap.to() のプロパティに直接書ける!

gsap.fromTo(btn, {
  // CSS変数名(文字列)をそのままプロパティに指定するだけ!
  '--ripple-scale': 1,
  '--ripple-opacity': 0.8,
}, {
  '--ripple-scale': 1.5, // 1.5倍まで拡大
  '--ripple-opacity': 0, // 同時に透明にする
  duration: 0.6,
  ease: 'power2.out'
});

GSAPでのCSS変数の操作ですが、とても簡単です。 x や opacity などを指定するのと同じように、'--ripple-scale': 1.5 のようにクォーテーションで囲んでプロパティとして渡すだけで、GSAPが自動的に数値を計算して滑らかにアニメーションさせてくれます!

CSS側に transition を書かないのが鉄則!

/* 擬似要素(::before)で作る波紋のベース */
.c-ripple-btn::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 30px;
  background-color: #1bb4d4;
  z-index: -1;
  pointer-events: none;
  
  /* 💡ポイント2: CSS変数を割り当てる(※CSSのtransitionは書きません!) */
  transform: scale(var(--ripple-scale));
  opacity: var(--ripple-opacity);
}

擬似要素(::before)のCSSを見るとわかりますが、動きを滑らかにするための transition プロパティは記述していません。 なぜなら、GSAPが毎フレームごとの細かい数値を計算して直接書き換えてくれるからです。ここでCSSの transition を書いてしまうと、GSAPの計算とCSSのアニメーションが衝突してガクガクした不自然な動きになってしまうので注意しましょう。

数値を持たせることで無限の応用が可能

今回は scaleと opacityを動かしましたが、CSS変数には角度や色コードを持たせることも可能です。GSAPの強力なイージング(ease)と組み合わせることで、CSSだけでは表現しきれない複雑でリッチな擬似要素アニメーションを作ることができます。

まとめ

今回は、GSAPを使ってCSS変数を直接操作し、擬似要素をアニメーションさせる方法を解説しました。

「擬似要素はJSで直接いじれない」という弱点も、CSS変数を経由させることで、GSAPの強力なアニメーション機能を余すことなく活用できるようになります。 以前の記事で紹介した「擬似要素の動的なスタイル変更」と、今回の「GSAPでの擬似要素アニメーション」。この2つのアプローチをマスターすれば、フロントエンドにおけるUI表現の幅が大きく広がります!ぜひ皆さんのWeb制作でも取り入れてみてください。

Prev
Next