こんにちは、Webディレクター兼フロントエンドエンジニアのBigViです。ホーチミンから日本に移り住んで、現在は東京で暮らしてます。今日はWeb制作でよく使う「アニメーションの使い方」について話したいと思います。いっぱいアニメーションをつけることもよくありますが、今回は「さりげなさ」をキーワードに、JavaScriptを使ったアニメーションの実装方法を紹介します。
目立ちすぎない、心地よいUIを目指して
Web制作をしていると、クライアントから「もっと目立たせたい」や「動きを加えたい」との依頼がよくあります。アニメーションは確かに目を引きますが、動きが多すぎるとユーザーが混乱したり、ページの表示が重くなったりします。そこで使うのが、軽くてさりげないアニメーションです。
タイピング風アニメーション
文章が一気に表示されるより、タイプライター風に一文字ずつ表示されると、人は自然に注目して読むようになる。とくにキャッチコピーやサービス名の紹介で効果がある。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>タイプライター風</title>
<style>
body { font-family: system-ui, -apple-system, sans-serif; padding: 24px; }
.typewriter { font: 700 28px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre; }
.controls { margin-top: 12px; }
@media (prefers-reduced-motion: reduce) {
.cursor { animation: none !important; }
}
.cursor { display: inline-block; width: 1ch; }
.cursor::after { content: "▍"; animation: blink 1s steps(2, jump-none) infinite; }
@keyframes blink { 50% { opacity: 0; } }
</style>
</head>
<body>
<div class="typewriter" id="tw"><span class="cursor"></span></div>
<div class="controls">
<button id="restart">Restart</button>
</div>
<script>
(function(){
const el = document.getElementById('tw');
const text = "静かな動きで、読みやすさを助ける。";
const speed = 80; // ms per char
function typeWriter() {
el.textContent = "";
let i = 0;
function step(){
if (i <= text.length) {
el.textContent = text.slice(0, i);
i++;
setTimeout(step, speed);
} else {
// 末尾にカーソルっぽい見た目
el.insertAdjacentHTML("beforeend", '<span class="cursor"></span>');
}
}
step();
}
document.getElementById('restart').addEventListener('click', typeWriter);
typeWriter();
})();
</script>
</body>
</html>
背景グラデーションのゆるやかな変化
要素の背景色がとてもゆっくりグラデーションで変わると、落ち着いた雰囲気になります。動きは小さいけど、印象は大きいです。
<div class="card">これはハッキリ動くグラデーション!</div>
/* 画面中央に配置するための最低限 */
html, body {
height: 100%;
}
body {
margin: 0;
display: grid;
place-items: center;
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
background: #000;
}
/* はっきり動くグラデーション */
.card {
padding: 40px 56px;
border-radius: 16px;
color: #fff;
font-size: 24px;
text-align: center;
/* コントラスト強めの色を並べる */
background: linear-gradient(270deg, red, blue, yellow, green);
background-size: 200% 200%;
/* 6秒で左右に往復(誰でも“動いてる”と分かる) */
animation: gradientShift 6s linear infinite;
box-shadow: 0 10px 30px rgba(0,0,0,.3);
}
@keyframes gradientShift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
通知バッチ:数字更新で“ちょっと弾む”
ただ数字が変わるより、少しだけ弾むと「更新された」とすぐわかる。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>通知バッジ:ほどよいバウンス</title>
<style>
body { font-family: system-ui; padding: 24px; }
.wrap { display: inline-flex; align-items: center; gap: 12px; }
.badge {
display: inline-grid; place-items: center;
min-width: 32px; height: 32px; padding: 0 8px;
border-radius: 16px;
background: #111; color: #fff; font-weight: 700;
will-change: transform;
transform-origin: center center;
font-size: 16px;
}
.bounce {
animation: badge-bounce 0.6s cubic-bezier(.25,1.3,.5,1);
}
/* やりすぎないけどしっかり見える振れ幅 */
@keyframes badge-bounce {
0% { transform: translateY(0) scale(1); }
20% { transform: translateY(-18%) scale(1.25); } /* 少し大きく上に */
40% { transform: translateY(8%) scale(0.9); } /* ちょっと潰れる */
60% { transform: translateY(-8%) scale(1.1); } /* 軽く跳ね返る */
80% { transform: translateY(3%) scale(0.97); } /* 減衰 */
100% { transform: translateY(0) scale(1); } /* 戻る */
}
</style>
</head>
<body>
<div class="wrap">
<button id="add">メッセージを追加</button>
<span class="badge" id="badge">0</span>
</div>
<script>
(function(){
const badge = document.getElementById('badge');
const add = document.getElementById('add');
add.addEventListener('click', () => {
const n = parseInt(badge.textContent || "0", 10) + 1;
badge.textContent = String(n);
badge.classList.remove('bounce');
void badge.offsetWidth; // reflowでリセット
badge.classList.add('bounce');
});
})();
</script>
</body>
</html>
詳細情報の開閉に“気持ちいい矢印”
クリックで開くFAQなどは、矢印がわずかに回るだけで理解しやすくなります。CSSだけで実装できるので動作も軽いです。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>矢印が回転するサンプル</title>
<style>
body { font-family: system-ui; padding: 24px; }
details {
width: 560px; border: 1px solid #ddd; border-radius: 12px; padding: 12px 16px;
}
summary {
list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px; font-size: 18px;
}
summary::-webkit-details-marker { display: none; }
.arrow {
width: 32px; height: 32px; /* ← 少し大きめ */
flex: 0 0 auto;
transition: transform .3s ease; /* ← スムーズに回転 */
transform-origin: 50% 50%;
transform: rotate(0deg); /* 閉時は「右向き」 */
}
details[open] .arrow {
transform: rotate(90deg); /* 開時は「下向き」 */
}
</style>
</head>
<body>
<details>
<summary>
<!-- 右向きシェブロン(Materialの形に近いパス) -->
<svg class="arrow" viewBox="0 0 24 24" aria-hidden="true">
<path d="M9 6l6 6-6 6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
このアニメーション、重くない?
</summary>
<p>いいえ。CSSの transform だけ使うので軽いです。</p>
</details>
</body>
</html>
まとめ
「さりげない」アニメーションは、控えめすぎて、提案する時だとお客様に理解してもらえないことが多いです。でも実際にコードにしてお客様に見ていただければわかるはずです。たくさん動作するアニメーションを入れることも良いのですが、たまにはこういう方法も試してみてください。
ぜひ次のプロジェクトで、これらの手法を試してみてください。サポートが必要な場合は、お問い合わせください。株式会社ファストコーディングでは、Webサイトのアニメーション実装をはじめとするさまざまなサポートを行っています。