チェックマークや下線が、ペンで描くようにスッと引かれていく。この動きは、SVG(線や図形を数字で描く画像の形式)の線に、CSSのアニメーションを付けると作れます。JavaScriptはいりません。
使いどころは「一度だけ、目を向けてほしい場所」です。送信が終わった合図や、いちばん伝えたい一言に使います。ページ中の線を全部描かせると、どこを見ればいいか分からなくなります。
この記事の要点
- SVGの線に pathLength=”1″ を付け、stroke-dasharray と stroke-dashoffset を1から0へ動かすと、線が描かれていく動きがCSSだけで作れる
- 使いどころは、送信完了の合図や、いちばん伝えたい一言など「一度だけ目を向けてほしい場所」。描くのは1回で止める
- 「動きを減らす」設定の人には最初から描き終わった線を見せる。ページの下のほうでは、画面に入ってから描く
完成見本:線が描かれていく4種類
下の4つは、ページを開いた時点から、描いては少し止まり、また描き直す動きを自動でくり返しています。くり返しているのは見本だからで、コピペ用のコードは1回描いたら止まります。
※ 見本は読み上げソフトでは読まれないようにしています。
コピペ用のコード
HTMLは線を描きたい場所に、CSSはサイトのCSSファイルや、WordPressならテーマの「追加CSS」などに入れます。1のCSSの前半(.kd-ld-line と @keyframes)は、4種類に共通する部分です。同じページで何種類か使うときも、1回だけ入れれば足ります。クラス名の頭の kd-ld は、サイトのほかのデザインと名前がぶつからないようにするための目印です。
1. チェックマークを描く
丸を描いてから、チェックを描く形です。どちらも path(線の通り道を表すSVGの部品)で、pathLength="1" を付けています。2本目のチェックには style="--i: 2" を書いて、丸を描き終わるころに描き始めるようにしています。
<svg class="kd-ld-check" viewBox="0 0 52 52" role="img" aria-label="送信しました">
<path class="kd-ld-line" pathLength="1" d="M26 4a22 22 0 1 1 0 44a22 22 0 1 1 0-44"/>
<path class="kd-ld-line" pathLength="1" style="--i: 2" d="M15 27l7 7 15-15"/>
</svg>/* 描かれる線。pathLength="1" を付けた線の長さを「1」として扱う */
.kd-ld-line {
fill: none;
stroke: #0284C7;
stroke-width: 4;
stroke-linecap: round;
stroke-linejoin: round;
stroke-dasharray: 1;
stroke-dashoffset: 1;
animation: kd-ld-draw 1.2s ease-out forwards;
animation-delay: calc(.3s + var(--i, 0) * .5s);
}
/* 線を「ずらした状態」から「ずれなし」へ動かすと、線が描かれていくように見える */
@keyframes kd-ld-draw {
to { stroke-dashoffset: 0; }
}
/* 動きを減らす設定の人には、最初から描き終わった線を見せる */
@media (prefers-reduced-motion: reduce) {
.kd-ld-line {
animation: none;
stroke-dashoffset: 0;
}
}
.kd-ld-check {
display: block;
width: 96px;
height: 96px;
}
/* チェックは、丸より速く描く */
.kd-ld-check .kd-ld-line + .kd-ld-line {
animation-duration: .6s;
}2. 手書き風の下線を引く
言葉の下に、波打つ線を引く形です。言葉を .kd-ld-mark の箱で囲み、SVGを position: absolute で言葉の下に重ねています。SVGは飾りなので aria-hidden="true" で読み上げから外しています。
<p>今日は<span class="kd-ld-mark">ここだけ覚えて
<svg viewBox="0 0 200 12" preserveAspectRatio="none" aria-hidden="true" focusable="false">
<path class="kd-ld-line" pathLength="1" d="M2 8C20 2 34 2 52 7S86 12 104 7 138 2 156 7 182 10 198 5"/>
</svg></span>ください。</p>/* 言葉の下に、手書き風の線を引く */
.kd-ld-mark {
position: relative;
display: inline-block;
font-weight: 700;
}
.kd-ld-mark svg {
position: absolute;
left: 0;
bottom: -10px;
width: 100%;
height: 14px;
overflow: visible;
}3. 言葉を丸で囲む
言葉のまわりを、手で描いたような丸で囲む形です。SVGを言葉より上下左右に少し大きく重ね、preserveAspectRatio="none"(縦横の比率を合わせず、箱いっぱいに伸ばす指定)で、言葉の長さに合わせて丸が伸びるようにしています。
<p>今月だけ<span class="kd-ld-circle">50%OFF
<svg viewBox="0 0 200 56" preserveAspectRatio="none" aria-hidden="true" focusable="false">
<path class="kd-ld-line" pathLength="1" d="M30 8C80 -2 170 0 192 24C206 44 130 60 60 54C10 50 -4 30 14 16C30 4 70 2 96 4"/>
</svg></span>です。</p>/* 言葉を、手で描いたような丸で囲む */
.kd-ld-circle {
position: relative;
display: inline-block;
margin: 0 .5em;
padding: 0 .3em;
font-weight: 700;
}
.kd-ld-circle svg {
position: absolute;
left: -12px;
top: -10px;
width: calc(100% + 24px);
height: calc(100% + 20px);
overflow: visible;
}
.kd-ld-circle .kd-ld-line {
stroke: #DC2626;
stroke-width: 3;
}4. 線画のアイコンを順に描く
屋根・壁・ドアの3本の線で家のアイコンを描き、1本ずつ順番に描く形です。2本目に --i: 1、3本目に --i: 2 を書くと、1のCSSの animation-delay の計算で、0.5秒ずつ遅れて描き始めます。
<svg class="kd-ld-icon" viewBox="0 0 56 56" role="img" aria-label="ホーム">
<path class="kd-ld-line" pathLength="1" d="M6 27L28 8l22 19"/>
<path class="kd-ld-line" pathLength="1" style="--i: 1" d="M13 22v26h30V22"/>
<path class="kd-ld-line" pathLength="1" style="--i: 2" d="M24 48V36h8v12"/>
</svg>/* 線画のアイコン。線を1本ずつ、順番に描く */
.kd-ld-icon {
display: block;
width: 120px;
height: 120px;
}1と4のSVGには role="img" と aria-label(読み上げソフトに伝える名前)を付けています。チェックの横に「送信しました」と文字で書くときは、同じことを2回読まれないように、SVGを aria-hidden="true" にしてください。
仕組み:点線の「すき間」を線の長さにして、ずらす
stroke-dasharray:線を点線にする指定
stroke-dasharray は、SVGの線を「線の部分」と「すき間」のくり返し、つまり点線にする指定です。stroke-dasharray: 5 なら、5の長さの線と5の長さのすき間が交互に並びます。
ここで、線の部分とすき間を、どちらも「線全体の長さ」にしてみます。すると「線全体ぶんの線」と「線全体ぶんのすき間」が並ぶだけになり、見た目は普通の1本の線になります。
stroke-dashoffset:点線をずらす指定
stroke-dashoffset は、点線の模様を、どれだけずらして始めるかの指定です。線全体の長さぶんずらすと、線の上には「すき間」だけが来て、何も見えなくなります。そこから0までずらし直すと、すき間が抜けていき、代わりに線の部分が始まりから順に入ってきます。これが「線が描かれていく」ように見える仕組みです。
pathLength=”1″ で、線の長さを「1」と決める
本来は、線ごとの実際の長さを調べて、その数を stroke-dasharray に書く必要があります。SVGの pathLength 属性を使うと、線の長さを作る人が決めた数で扱えます。pathLength="1" と書けば、長い線も短い線も、長さは「1」です。だからCSSは stroke-dasharray: 1 と stroke-dashoffset: 1 の1組だけで、どの線にも使えます。
MDNの対応表では、path に付けた pathLength は、Chrome 50・Firefox 6・Safari 14から使えます。
順番に描く:–i で待ち時間をずらす
1のCSSの animation-delay: calc(.3s + var(--i, 0) * .5s) は、「0.3秒待つ。さらに、–i の数×0.5秒待つ」という意味です。--i はCSSの変数(自分で名前を付けた入れ物)で、書いていない線は0として扱います。HTMLで線ごとに style="--i: 1" のように書くと、0.5秒ずつ遅れて描き始めます。
数値を変えるとどうなるか
描く時間:animation の秒数
0.4秒(左)では、動いたことに気づいた時には描き終わっていて、描く動きが伝わりません。3秒(右)では、全部描き終わるまで4秒以上かかり、待たされる感じが出ます。1本あたり0.8〜1.5秒あたりが、描く動きが見えて、待たされない範囲です。
pathLength=”1″ を付け忘れると
pathLength="1" がないと、stroke-dasharray: 1 は「SVGの中の長さで1の線と、1のすき間」という、ごく細かい点線になります。線の太さ(4)のほうがすき間より大きいので、丸い線の端がすき間をうめて、1本の線に見えます(左)。ずらす量も1だけなので、描かれる動きは起きず、最初から全部見えたままです。線が描かれずにそのまま出ていたら、まず pathLength を確かめます。
| 変えるところ | 指定 | 今回の値 | 目安 |
|---|---|---|---|
| 1本を描く時間 | animation の秒数 | 1.2秒 | 0.8〜1.5秒 |
| 描き始めるまで | animation-delay | 0.3秒 | 0.2〜0.5秒 |
| 次の線までの間 | –i × ○秒 | 0.5秒 | 前の線が半分ほど描けたころ |
| 線の太さ | stroke-width | 4(丸は3) | 文字の太さに近づける |
| 線の端の形 | stroke-linecap | round(丸) | 手書き風なら round |
スマホと、見る人への配慮
「動きを減らす」設定の人には、描き終わった線を見せる
画面の動きが苦手な人は、スマホやパソコンで「動きを減らす」設定をオンにしていることがあります。prefers-reduced-motion を使い、この設定の人には動きを止め、stroke-dashoffset: 0 で最初から描き終わった線を見せています。動きを止めるだけだと、線が「すき間」のまま隠れて、何も見えなくなるためです。
くり返さない
コピペ用のコードは、forwards(描き終わった形で止める指定)で1回だけ描いて止まります。WCAG(ウェブのアクセシビリティの国際的な基準)2.2の達成基準2.2.2では、自動で始まって5秒より長く続く動きには、止める方法を用意することとされています。描き直しをくり返すと、この基準に当てはまるうえ、読んでいる人の目が何度も引っぱられます。
線の色は、背景との差をつける
細い線は、色が薄いと見えにくくなります。KAKERUブルー(#0EA5E9)は白地との明るさの差が約2.8:1なので、見本の線には濃い #0284C7(約4.1:1)を使っています。丸で囲む赤は #DC2626(約4.8:1)です。
スマホでは、線の太さと大きさを確かめる
アイコンを小さく表示すると、線も一緒に細くなります。stroke-width はSVGの中の長さなので、アイコンを半分の大きさにすると、線の太さも半分になります。スマホの幅で見て、線が細すぎないかを確かめます。

線が描かれる動きは、きれいなので、つい何か所にも使いたくなります。
でも、全部が動くと、どれも目に留まらなくなります。1画面に1か所までにしています。
応用:画面に入ってから描く
CSSのアニメーションは、ページを開いた瞬間に始まります。ページの下のほうに置いた線は、そこまでスクロールしたときには描き終わっていて、動きが見えません。そこで、画面に入るまで動きを止めておき、入ったら描き始めるようにします。
線の外側の箱(SVGや、言葉を囲んだ span)に kd-ld-wait というクラスを足し、下のCSSとJavaScriptを入れます。animation-play-state: paused は、アニメーションを止めておく指定です。JavaScriptの IntersectionObserver(要素が画面に入ったかを知らせる仕組み)で、半分ほど見えたらクラスを外して描き始めます。
/* 画面に入るまで、描く動きを止めておく */
.kd-ld-wait .kd-ld-line {
animation-play-state: paused;
}/* 半分ほど画面に入ったら .kd-ld-wait を外して、描き始める(1回だけ) */
(function () {
function go() {
var els = document.querySelectorAll('.kd-ld-wait');
if (!('IntersectionObserver' in window)) {
els.forEach(function (el) { el.classList.remove('kd-ld-wait'); });
return;
}
var io = new IntersectionObserver(function (list) {
list.forEach(function (e) {
if (e.isIntersecting) {
e.target.classList.remove('kd-ld-wait');
io.unobserve(e.target);
}
});
}, { threshold: 0.5 });
els.forEach(function (el) { io.observe(el); });
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', go);
else go();
})();下の見本は、このクラスを付けています。ここまでスクロールして、半分ほど見えたときに描き始めます(1回だけ)。
※ スクロールでふわっと表示する動きの作り方は、連載の「スクロールでふわっと表示」の回でくわしく紹介しています。
AIに頼むなら
同じような動きは、Claudeなどの生成AIに頼んでもすぐ作れます。そのときは、見た目だけでなく、描く時間・回数・動きを減らす設定まで伝えると、直す回数が減ります。
送信完了の画面に、丸とチェックマークが線で描かれるSVGアニメーションを付けたい。
CSSだけで、pathLength="1" と stroke-dashoffset を使い、丸1.2秒→チェック0.6秒で1回だけ描いて止める。
「動きを減らす」設定の人には、最初から描き終わった形を見せて。線の色は #0284C7。AIが出したコードは、そのまま使う前に、次の3つを確かめます。
- 「動きを減らす」設定で、線が消えていないか。
animation: noneだけだと線が隠れたままになります。stroke-dashoffset: 0も書かれているかを見ます - JavaScriptで線の長さを測っていないか。
getTotalLength()で長さを測るコードでも動きますが、pathLength="1"を付ければCSSだけで足ります。短いほうが直しやすいです - infinite(無限にくり返す)になっていないか。見本のようにくり返すと、5秒を超える動きになります。1回で止まる形にします
KAKERUならこう使う/使わない
最後に、作り手としての判断です。
使う場面
- 送信・保存が終わった合図に「チェックマーク」。お問い合わせフォームの送信後など、「ちゃんと届いた」と伝えたい画面に使います
- キャッチコピーの一言に「下線」か「丸」。トップページの最初の画面で、いちばん伝えたい言葉1つだけに使います
- サービス紹介のアイコンに「線画を順に描く」。3〜4つ並んだアイコンを、画面に入ったときに1回だけ描きます
使わない場面
- 本文の中のあちこち。強調したい場所が何か所もあるなら、動きではなく太字や色で分けます
- 読み終わるまで待たせる場所。線を描き終わるまで次の文が出ない、という作りにはしません
- 細かい図やイラスト全体。線が多い絵を全部描かせると時間がかかり、描き終わる前にスクロールされます

KAKERUなら、「この線が描かれると、何が伝わるか」を先に決めます。
答えが「送信できた」「ここが大事」のように一言で言えるときだけ、線を動かします。
まとめ
- 線が描かれる動きは、SVGの線と、CSSの stroke-dasharray・stroke-dashoffset で作れる
- pathLength=”1″ を付けると、どの線も長さ1として扱えて、CSSが1組で済む
- 1本は0.8〜1.5秒、順に描くなら –i と animation-delay で0.5秒ずつずらす
- 「動きを減らす」設定では描き終わった線を見せる。くり返さず、1回で止める
- 使うのは、送信完了の合図やいちばん伝えたい一言など、1画面に1か所
まずは1の「チェックマークを描く」をコピーして、線の色や秒数を変えてみてください。
参考にした資料
いずれも2026年10月30日に確認しました。ブラウザの対応状況は変わることがあります。最新の情報は各ページでご確認ください。
- MDN「stroke-dasharray」(英語)
https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/stroke-dasharray
※線を「線の部分」と「すき間」のくり返しにする指定。Baseline(主要ブラウザで広く使える) - MDN「stroke-dashoffset」(英語)
https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/stroke-dashoffset
※線とすき間のくり返しを、どれだけずらして始めるかの指定。Baseline - MDN「pathLength」(英語)
https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/pathLength
※線の長さを、作る人が決めた数で扱えるようにする属性。stroke-dasharray もこの長さを基準にすること。対応状況はChrome 50・Firefox 6・Safari 14から(path の場合) - MDN「SVGGeometryElement: getTotalLength()」(英語)
https://developer.mozilla.org/en-US/docs/Web/API/SVGGeometryElement/getTotalLength
※JavaScriptで線の実際の長さを調べる方法 - MDN「animation-play-state」(英語)
https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/animation-play-state
※アニメーションを止めておく・動かす指定 - MDN「prefers-reduced-motion」(英語)
https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-reduced-motion
※「動きを減らす」設定をしている人を見分けるメディア特性 - W3C WAI「Understanding SC 2.2.2: Pause, Stop, Hide」(英語)
https://www.w3.org/WAI/WCAG22/Understanding/pause-stop-hide.html
※自動で始まり5秒より長く続く動きには、止める方法を用意すること(レベルA)
ふだんの制作の話や、作ったものの裏側は Instagram と X でも出しています。


























連載「WEBの技術」の33回目です。
今回は、線が描かれていくアニメーション。1回目のローディングと同じく、動きで目を向けてもらう技術です。