2026年5月20日
2026年5月20日
WordPressでSVGアニメーションを使う方法(CSS・SMIL・Lottie)
SVG はベクター形式の画像なので、拡大しても粗くならず、CSS や SVG 自体の機能で動かせます。ローディング表示の回転、チェックマークを描く動き、アイコンの点滅などを、動画や GIF を使わずに作れます。
この記事では、WordPress のテーマやページで SVG アニメーションを使う方法を、置き場所の選び方から順に説明します。コードは、テーマ(子テーマ)を編集できることを前提にしています。
SVG をどこに置くかで、できることが変わる
| 置き方 | CSS アニメーション | SMIL | ページ側の CSS・JavaScript から操作 |
|---|---|---|---|
HTML の中に <svg> を直接書く(インライン SVG) |
使える | 使える | できる |
<img src="icon.svg"> で読み込む |
SVG ファイルの中の <style> なら動く |
動く | できない |
CSS の background-image で読み込む |
SVG ファイルの中の <style> なら動く |
動く | できない |
<img> や背景画像として読み込んだ SVG は、ページとは別の文書として扱われます。SVG ファイルの中に書いたアニメーションは動きますが、ページ側の CSS で中の図形の色や動きを変えたり、JavaScript でスクロールに合わせて動かし始めたりすることはできません。この記事の例は、操作しやすいインライン SVG を中心にしています。
方法1: インライン SVG を CSS で回転させる
ローディング表示のように、SVG 全体を回転させる例です。テーマのテンプレートファイル(PHP)や、ブロックエディターの「カスタム HTML」ブロックに次の SVG を書きます。
<svg class="icon-spin" xmlns="http://www.w3.org/2000/svg"
width="40" height="40" viewBox="0 0 24 24" aria-hidden="true">
<circle cx="12" cy="12" r="10" fill="none"
stroke="#2271b1" stroke-width="2" stroke-dasharray="48 15"/>
</svg>
CSS はテーマ(子テーマ)の style.css か、「追加 CSS」に書きます。
.icon-spin {
animation: icon-spin 1s linear infinite;
}
@keyframes icon-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* 動きを減らす設定にしている人には止める */
@media (prefers-reduced-motion: reduce) {
.icon-spin {
animation: none;
}
}
外側の <svg> 要素は HTML の要素と同じように扱われるため、中心を軸に回ります。SVG の中の図形(<circle> や <path>)を回す場合は、既定では SVG 全体の左上が回転の中心になります。図形の中心で回すには、その図形に次の指定を加えます。
.icon-spin circle {
transform-box: fill-box;
transform-origin: center;
}
「カスタム HTML」ブロックに書くときの注意
インライン SVG と <style> をブロックエディターに書けるのは、unfiltered_html の権限を持つユーザー(単一サイトでは管理者と編集者、マルチサイトではネットワーク管理者)だけです。投稿者や寄稿者が保存すると、許可されていないタグとして取り除かれます。何度も使う SVG は、テーマのテンプレートやテンプレートパーツに置くほうが管理しやすくなります。
方法2: 線を描くストロークアニメーション
円とチェックマークが描かれていくように見せる例です。線の長さと同じ値を stroke-dasharray と stroke-dashoffset に入れて線を隠し、stroke-dashoffset を 0 まで動かします。
<svg class="checkmark" xmlns="http://www.w3.org/2000/svg"
width="60" height="60" viewBox="0 0 52 52" aria-hidden="true">
<circle class="checkmark-circle" cx="26" cy="26" r="25"
fill="none" stroke="#00a32a" stroke-width="2"/>
<path class="checkmark-check" fill="none" stroke="#00a32a"
stroke-width="3" d="M14.1 27.2l7.1 7.2 16.7-16.8"/>
</svg>
/* 円周 = 2 × 3.1416 × 25 ≒ 157.1 なので 158 を使う */
.checkmark-circle {
stroke-dasharray: 158;
stroke-dashoffset: 158;
animation: checkmark-draw 0.6s ease-out forwards;
}
/* チェックの線の長さは約 33.8 なので 34 を使う */
.checkmark-check {
stroke-dasharray: 34;
stroke-dashoffset: 34;
animation: checkmark-draw 0.3s ease-out 0.6s forwards;
}
@keyframes checkmark-draw {
to { stroke-dashoffset: 0; }
}
/* 動きを止める場合は、線を描き終えた状態で表示する */
@media (prefers-reduced-motion: reduce) {
.checkmark-circle,
.checkmark-check {
animation: none;
stroke-dashoffset: 0;
}
}
線の長さが正確にわからない図形では、ブラウザの開発者ツールのコンソールで document.querySelector('.checkmark-check').getTotalLength() を実行すると長さを確認できます。
動きを止めるときに animation: none だけを書くと、線が隠れたままになり何も表示されません。上のように stroke-dashoffset: 0 もあわせて指定します。
方法3: SMIL(SVG のアニメーション要素)を使う
SVG には、図形の中に <animate> などの要素を書いて動かす仕組み(SMIL)もあります。CSS を別に用意しなくてよく、<img> で読み込んだ SVG ファイルの中でも動きます。
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="20"
viewBox="0 0 60 20" role="img" aria-label="読み込み中">
<circle cx="10" cy="10" r="6" fill="#2271b1">
<animate attributeName="opacity" values="1;0.2;1" dur="1.2s" repeatCount="indefinite"/>
</circle>
<circle cx="30" cy="10" r="6" fill="#2271b1">
<animate attributeName="opacity" values="1;0.2;1" dur="1.2s" begin="0.2s" repeatCount="indefinite"/>
</circle>
<circle cx="50" cy="10" r="6" fill="#2271b1">
<animate attributeName="opacity" values="1;0.2;1" dur="1.2s" begin="0.4s" repeatCount="indefinite"/>
</circle>
</svg>
SMIL の動きは CSS の prefers-reduced-motion では止まりません。動きを減らす設定に対応したい場合は、CSS アニメーションで作るか、インライン SVG なら JavaScript で SVG 要素の pauseAnimations() を呼んで止めます。
方法4: スクロールして見えたときに動かす
方法2 のチェックマークを、画面に入ったときに動かし始める例です。JavaScript が is-visible クラスを付けたときだけアニメーションを始めるように、CSS を書き換えます。
.animate-on-scroll .checkmark-circle,
.animate-on-scroll .checkmark-check {
animation-play-state: paused;
}
.animate-on-scroll.is-visible .checkmark-circle,
.animate-on-scroll.is-visible .checkmark-check {
animation-play-state: running;
}
SVG に class="checkmark animate-on-scroll" のようにクラスを足し、次の JavaScript を読み込みます(読み込み方は方法5 の wp_enqueue_script と同じです)。
// 要素が 30% 見えたら is-visible を付け、以後は監視をやめる
const targets = document.querySelectorAll('.animate-on-scroll');
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('is-visible');
observer.unobserve(entry.target);
}
});
}, { threshold: 0.3 });
targets.forEach((el) => observer.observe(el));
この方法では、JavaScript が動かない環境ではアニメーションが止まったまま(線が隠れたまま)になります。表示されないと困る図形には使わないか、JavaScript で animate-on-scroll クラスを付けるように変えます。
方法5: Lottie のアニメーションを表示する
Lottie は、After Effects などで作ったアニメーションを JSON ファイルにし、ブラウザで SVG として再生する仕組みです。再生には lottie-web というライブラリを使います。
手順1: JSON ファイルをテーマに置く
WordPress のメディアライブラリは、初期設定では JSON ファイルのアップロードを受け付けません。アニメーションの JSON ファイルは、子テーマの中(例: animations/hero.json)に置きます。
手順2: lottie-web と初期化用のスクリプトを読み込む
子テーマの functions.php に次を追加します。例の lottie-web 5.13.0 は、2026年10月時点で cdnjs にある版です。
<?php
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_script(
'lottie-web',
'https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.13.0/lottie.min.js',
array(),
'5.13.0',
array( 'in_footer' => true )
);
wp_enqueue_script(
'mytheme-lottie-init',
get_theme_file_uri( 'js/lottie-init.js' ),
array( 'lottie-web' ),
'1.0.0',
array( 'in_footer' => true )
);
} );
get_theme_file_uri() は、子テーマにファイルがあれば子テーマの URL を、なければ親テーマの URL を返します。外部の CDN を使いたくない場合は、lottie-web のファイルをテーマに置いて読み込みます。
子テーマに js/lottie-init.js を作り、data-lottie 属性を持つ要素ごとにアニメーションを読み込みます。
// data-lottie 属性に書いた JSON ファイルを再生する
document.addEventListener('DOMContentLoaded', () => {
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
document.querySelectorAll('[data-lottie]').forEach((el) => {
lottie.loadAnimation({
container: el,
renderer: 'svg',
loop: el.dataset.lottieLoop !== 'false',
autoplay: !reduce, // 動きを減らす設定なら自動再生しない
path: el.dataset.lottie,
});
});
});
手順3: テンプレートに表示する場所を作る
テンプレートファイルに、表示する場所を書きます。
<div class="hero-animation"
data-lottie="<?php echo esc_url( get_theme_file_uri( 'animations/hero.json' ) ); ?>"
data-lottie-loop="true"
style="width: 300px; height: 300px;"
aria-hidden="true"></div>
JSON ファイルを別のドメイン(CDN など)に置く場合は、そのサーバーがクロスオリジンの読み込みを許可している必要があります。同じサイトに置けば、この設定は要りません。
SVG ファイルをメディアライブラリにアップロードしたい場合
WordPress は初期設定では SVG ファイルのアップロードを許可していません。SVG は中に JavaScript を書ける形式のため、upload_mimes フィルターで拡張子を足すだけで許可すると、悪意のあるスクリプトを含む SVG がアップロードされるおそれがあります。
アップロードを許可する場合は、アップロード時に中身を無害化(サニタイズ)するプラグインを使います。たとえば 10up が開発する「Safe SVG」は、enshrined/svg-sanitize というライブラリでアップロードされた SVG をサニタイズし、アップロードできるユーザーを制限する設定も持っています。
なお、<img> で表示する SVG では、ファイル内に書いた JavaScript は実行されません。それでも、SVG ファイルの URL を直接開かれるとスクリプトが動く場合があるため、サニタイズは省かないようにします。
アクセシビリティの注意
- 飾りの SVG には
aria-hidden="true"を付け、スクリーンリーダーが読み上げないようにします。意味のある SVG にはrole="img"とaria-labelを付けます。 - OS やブラウザで「視差効果を減らす」「アニメーションを減らす」を選んでいる人には、
prefers-reduced-motion: reduceで動きを止めるか小さくします。 - 5 秒を超えて動き続ける表示には、止める手段を用意することが Web アクセシビリティの指針(WCAG 2.2 の達成基準 2.2.2)で求められています。読み込み中で操作できない間だけ出るローディング表示は、例外として扱われます。
まとめ
- ページ側の CSS や JavaScript で動かすなら、SVG はインラインで書く。
<img>で読み込む場合は SVG ファイルの中に動きを書く - 回転などは
@keyframesとanimation、線を描く動きはstroke-dasharrayとstroke-dashoffsetで作る - SMIL は
<img>の中でも動くが、prefers-reduced-motionでは止まらない - Lottie は lottie-web を
wp_enqueue_scriptで読み込み、JSON はテーマの中に置く - SVG のアップロードは、サニタイズするプラグインを入れてから許可する