待ち時間を伝える3種のアニメーション
CSS の @keyframes で作る回転スピナー・ドット・不定形バーと、JavaScript で読み込み完了まで表示する制御を4パターンで解説します。各デモと同じ動きを再現できるHTML・CSS・JavaScriptを掲載しています。
HTML・CSS・JSコードプレビューツールでも動作を確認できます。
このページで作るもの
① 回転する円 — border の一部を濃くして回す
アニメーション: spin 1s linear infinite
<div class="ld-spin"></div>
.ld-spin {
width: 60px;
height: 60px;
border: 6px solid rgba(0, 0, 0, 0.15);
border-top: 6px solid #333;
border-radius: 50%;
animation: ldSpin 1s linear infinite;
}
@keyframes ldSpin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
薄いリングを border で作り、border-top だけ濃い色で上書きします。@keyframes で 0deg → 360deg に回すと、強調された部分がぐるぐる回るスピナーになります。速度ボタンを押すとデモとコピペ用CSSが同時に更新されます。
② ドットの拡大縮小 — animation-delay でリズムを作る
<div class="ld-dots">
<div class="ld-dot"></div>
<div class="ld-dot"></div>
<div class="ld-dot"></div>
</div>
.ld-dots {
display: flex;
gap: 20px;
}
.ld-dot {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #4f46e5;
animation: ldBounce 1.2s infinite ease-in-out;
}
.ld-dot:nth-child(1) {
animation-delay: -0.24s;
}
.ld-dot:nth-child(2) {
animation-delay: -0.12s;
}
.ld-dot:nth-child(3) {
animation-delay: 0s;
}
@keyframes ldBounce {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.5);
}
}
同じ @keyframes を3つのドットに適用し、animation-delay を -0.24s / -0.12s / 0s とずらすと波打つ動きになります。負の値はアニメーションを途中から始めるため、表示直後から動きが見えます。
③ 不定形プログレスバー — overflow ではみ出しを隠す
<div class="ld-bar-wrap">
<div class="ld-bar-inner"></div>
</div>
.ld-bar-wrap {
position: relative;
width: 100%;
max-width: 360px;
height: 20px;
overflow: hidden;
border-radius: 5px;
background-color: #e2e8f0;
}
.ld-bar-inner {
position: absolute;
width: 50%;
height: 100%;
background: linear-gradient(90deg, #7c3aed, #4f46e5);
animation: ldBarMove 2s infinite;
}
@keyframes ldBarMove {
0% {
left: -50%;
}
50% {
left: 25%;
}
100% {
left: 100%;
}
}
外枠に position: relative と overflow: hidden を付け、バーを absolute で動かします。left を枠外から枠外へ動かすと、はみ出しが隠れて終わりのない不定形バーになります。進捗%が分かるバーは プログレスバー記事 も参照してください。
④ 読み込み完了まで表示する — window load で制御
ページコンテンツ
2秒間のローディングが表示されます
<div class="ld-page-overlay">
<div class="ld-page-spin"></div>
</div>
<main>
<!-- ページ本体のコンテンツ -->
</main>
.ld-page-overlay {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: #fff;
}
body.is-ready .ld-page-overlay {
display: none;
}
.ld-page-spin {
width: 60px;
height: 60px;
border: 6px solid rgba(0, 0, 0, 0.15);
border-top: 6px solid #333;
border-radius: 50%;
animation: ldPageSpin 1s linear infinite;
}
@keyframes ldPageSpin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
window.addEventListener('load', function() {
document.body.classList.add('is-ready');
});
window の load は画像などを含むリソースの読み込み完了で発火します。このタイミングで body にクラスを付け、CSS でオーバーレイを非表示にします。デモの「ローディングを体験」は、同じ見え方を2秒間再現します。
スピナーとプログレスバーの違いは?
スピナーは「処理中」を伝えます。進捗%が分かる場合は決定型のプログレスバー、終わりが不明な場合は③の不定形バーやスピナーが向いています。
DOMContentLoaded との違いは?
DOMContentLoaded は HTML の解析完了時点です。load は画像などの読み込み完了後です。画像が多いページでオーバーレイを消すなら load の方が安全です。
動きを弱めたいときは?
prefers-reduced-motion: reduce で animation を止めるか、ゆっくりした動きに切り替えると配慮できます。
スケルトン表示との使い分けは?
レイアウトの骨組みを先に見せたいときは スケルトンスクリーン が向いています。単純な待ち表示ならスピナーで十分です。
当サイトで公開しているWebデザインやUIの実装例は、一覧として以下記事に纏めています。

