テクニック

SVGアニメーションの作り方|軽量でリッチな演出【コード付き】

この記事の対象: SVGアニメーションを実装したいフロントエンドエンジニア
読了時間: 約7分

ロゴが描かれるように表示される。アイコンがクリックひとつで滑らかに変形する。SVGアニメーションは、GIFやLottieと比べて圧倒的に軽量でありながら、解像度に依存しない美しい演出を実現できる手法です。この記事では、実装方法を3パターンに整理し、現場でそのまま使えるコード例を3つ紹介します。


SVGアニメーションとは

SVGアニメーションは、ベクターグラフィック(SVG)にモーションを加える技術です。拡大してもにじまない、ファイルサイズが小さい、インタラクションを後から付け足せるという3つの特性が、他のアニメーション形式との最大の違いになります。

フォーマット ファイルサイズ 解像度 インタラクション 適したケース
GIF 大きい 固定 不可 シンプルなループ
Lottie 中程度 可変 可能 複雑なアニメーション
SVG 非常に小さい 可変 可能 アイコン、ロゴ、図形

SVGはテキストベースのXMLフォーマットのため、gzip圧縮が効きやすく、ファイルサイズが極小になります。ロゴや装飾的なアイコンのアニメーションであれば、まずSVGで実現できないかを検討するのが合理的です。


SVGアニメーションの作り方3パターン

実装方法ごとの向き不向き

CSS animation

  • 手軽・ブラウザ対応が良い
  • ホバーや単発の演出向き

JavaScript(GSAP)

  • タイムライン制御が必要な演出向き
  • 学習コストはやや高め

SMILはSVG単体で完結する点が独特なので、個別に扱う。

CSS animation + SVG

SVGの各要素にCSSアニメーションを適用する方法です。最も手軽で、ブラウザ対応も安定しています。

/* SVG要素にCSSアニメーションを適用 */
.svg-icon path {
  transition: fill 0.3s ease;
}

.svg-icon:hover path {
  fill: #3b82f6;
}

ホバーで色を変える、クリックで拡大するといった単発の演出であれば、これだけで十分です。

SMIL(SVGネイティブアニメーション)

SVGの内部に<animate>タグでアニメーションを記述する方法です。JavaScriptもCSSも不要で、SVGファイル単体でアニメーションが動作します。

<circle cx="50" cy="50" r="20" fill="#3b82f6">
  <animate attributeName="r" from="20" to="30" dur="1s"
    repeatCount="indefinite" />
</circle>

メールやCMSの本文に直接埋め込みたいときなど、外部ファイルに依存できない環境ではこの方式が有効です。ただし新規実装では、同等の表現がCSSやJSでも可能な場面が多く、優先度は下がります。

JavaScript(GSAP + SVG)

GSAPを使えば、SVGのパス・変形・色をタイムラインで精密に制御できます。複数要素を順番に動かす、スクロールに連動させるといった複雑な演出は、GSAPが最も柔軟です。GSAPそのものの基本的な使い方は、下の記事にまとめています。


実装例3選

ラインアニメーション(stroke-dasharray)

ロゴやアイコンが「描かれるように」表示されるアニメーションです。ブランドのロゴ表示など、第一印象を作る場面で定番の演出になっています。

<svg viewBox="0 0 200 200" class="line-draw">
  <path d="M10,80 Q95,10 180,80 Q95,150 10,80"
    fill="none" stroke="#000" stroke-width="2" />
</svg>
.line-draw path {
  stroke-dasharray: 500;
  stroke-dashoffset: 500;
  animation: draw 2s ease forwards;
}

@keyframes draw {
  to {
    stroke-dashoffset: 0;
  }
}

仕組み: stroke-dasharrayでパスを破線にし、stroke-dashoffsetで破線の開始位置をずらすことで、パスが徐々に描かれる効果を作ります。数値の500はパスの全長に近い値を入れる必要があり、実際のパス長とズレると途中で止まって見えるので、path.getTotalLength()で正確な長さを取得してから設定するのが安全です。

モーフィング(パスの変形)

1つの形から別の形へ滑らかに変形するアニメーションです。

<svg viewBox="0 0 100 100">
  <path d="M25,50 a25,25 0 1,1 50,0 a25,25 0 1,1 -50,0" fill="#3b82f6">
    <animate attributeName="d"
      to="M10,10 L90,10 L90,90 L10,90 Z"
      dur="1s" fill="freeze"
      begin="click" />
  </path>
</svg>

円から四角形へのモーフィングです。SMILでも実現できますが、複雑な形状間の変形や、複数ステップの変形を扱うならGSAPのMorphSVGPluginのほうが安定します。パスの頂点数が異なる図形同士をモーフィングさせる場合は、事前にパスを補正するツールを通しておくと破綻しにくくなります。

マスクアニメーション

SVGのマスクを使って、コンテンツが段階的に表示される効果です。

<svg viewBox="0 0 400 200">
  <defs>
    <mask id="reveal-mask">
      <rect x="0" y="0" width="0" height="200" fill="white">
        <animate attributeName="width"
          from="0" to="400" dur="1.5s" fill="freeze" />
      </rect>
    </mask>
  </defs>
  <text x="20" y="120" font-size="48" mask="url(#reveal-mask)">
    Hello World
  </text>
</svg>

マスクのwidthをアニメーションさせることで、テキストが左から順に現れる効果を作ります。見出しのファーストビューや、スクロールに合わせて文字を見せる演出でよく使われます。


実装前に決めておきたい「どこで止めるか」

3つの実装例を組み合わせれば表現の幅は大きく広がりますが、コードが書けることと、良い演出になることは別の問題です。SVGアニメーションを設計する際は、次の3点を先に決めておくと手戻りが減ります。

  • 再生回数: ロゴの描画アニメーションのように「初回だけ見せたい」演出はrepeatCountを指定せず一度きりにする。ループさせるのはローディング表示など、意図的に注意を引き続けたい場面に限る
  • 再生時間: ラインアニメーションやマスクアニメーションは、長すぎると表示を待たされる印象を与え、短すぎると効果自体が見逃されます。1秒前後を起点に、実際の画面で調整するのが現実的です
  • 同時に動かす要素数: 複数のパスを同時にアニメーションさせると処理負荷が上がりやすいため、一度に動かす要素は必要最小限に絞る

こうした判断軸は、Soreiine!!ギャラリーに掲載されているサイトを見るときのチェックポイントにもなります。ロゴやアイコンのアニメーションが「効果のための効果」になっていないか、再生のタイミングと長さが自然かという視点で見ると、実装の参考にしやすくなります。


SVGの最適化(SVGO)

SVGファイルはIllustratorやFigmaから書き出すと、不要なメタデータや冗長な属性を含んでいることが多くあります。SVGOを使って最適化しましょう。

npx svgo input.svg -o output.svg

書き出し時に残る不要なコメントやエディタ独自の属性を取り除けるため、ファイルサイズの削減が期待できます。削減率はファイルの作り方によって変わるため、導入時は最適化前後のサイズを実際に比較して確認してください。

注意: アニメーションに使用するid属性やclass属性がSVGOで削除されないよう、設定でそれらを除外する必要があります。デフォルト設定のまま最適化をかけると、<animate>タグが参照しているidが消えてアニメーションが止まるケースがあるため、最適化後は必ず実機で動作確認をしてください。


アクセシビリティと実装時の注意点

SVGアニメーションは視覚的な効果が強い分、動きに敏感なユーザーへの配慮が欠かせません。OS側で「視差効果を減らす」設定が有効な場合は、アニメーションを止めるかシンプルな表示に切り替えるのが基本です。

@media (prefers-reduced-motion: reduce) {
  .line-draw path {
    animation: none;
    stroke-dashoffset: 0;
  }
}

この対応を入れておくだけで、演出の恩恵を受けられないユーザーに不要な負荷をかけずに済みます。LCP(Largest Contentful Paint)に関わる領域でSVGアニメーションを使う場合は、画像の遅延読み込みの考え方と合わせて検討すると、表示速度との両立がしやすくなります。


よくある質問

SVGアニメーションとLottieはどちらを選ぶべきですか

アイコンやロゴ程度のシンプルな図形であればSVGアニメーションが軽量で有利です。複数のレイヤーが絡む複雑なモーショングラフィックを再現したい場合は、After Effectsからの書き出しが前提になるLottieのほうが向いています。

stroke-dasharrayの数値はどう決めればいいですか

パスの全長に近い値を設定する必要があります。手動で調整するより、JavaScriptでpath.getTotalLength()を呼んで取得した値をそのままCSS変数やinline styleに渡す方法が確実です。

SMILは今でも使っても大丈夫ですか

主要ブラウザでの対応は維持されていますが、新規実装ではCSSアニメーションやJavaScriptで同等の表現ができることが多く、優先度は下がります。SVGファイル単体で完結させたい特殊な用途でのみ検討してください。

GSAPを導入するほどの演出かどうかの判断基準は何ですか

単発のホバーや1つのパスを描くだけならCSSで十分です。複数要素を順番に動かす、スクロールに連動させる、クリックで複雑なタイムラインを再生するといった要件が出てきた時点でGSAPの導入を検討してください。

SVGアニメーションがモバイルで重くなるのはなぜですか

一度に多くのパスを同時にアニメーションさせると、特に低スペック端末で描画負荷が高くなります。will-change: transformの指定や、同時に動かす要素数を絞ることで改善できる場合があります。


まとめ

SVGアニメーションのポイントをまとめます。

  • GIFやLottieより軽量でリッチな演出が可能
  • CSS animationで手軽に、GSAPで高度に実装できる
  • ラインアニメーション(stroke-dasharray)はロゴ表示の定番
  • SVGOで最適化してファイルサイズを削減する
  • prefers-reduced-motionでの停止対応を忘れない

実装方法を選ぶときは、「演出の複雑さ」と「導入コスト」のバランスで判断するのが近道です。まずCSSで実現できないかを検討し、足りない場合にのみGSAPを検討する順序で進めると、無駄な依存関係を増やさずに済みます。

AIコーディングを使ってSVGアニメーションの実装を効率化したい場合は、現場での使いどころを整理した記事も参考にしてください。