DEMO
CODE
<div class="demo-stage png-stage">
<ul class="png-list">
<li class="png-row"><span class="png-dot png-red" data-on="true" aria-hidden="true"></span><span class="png-name">配信中</span><span class="png-badge">LIVE</span></li>
<li class="png-row"><span class="png-avatar" aria-hidden="true">K<span class="png-dot png-dot-sm" data-on="true"></span></span><span class="png-name">Kappy</span><span class="png-state" id="png-state" aria-live="polite">オンライン</span></li>
<li class="png-row"><span class="png-bell" aria-hidden="true">🔔<span class="png-dot png-dot-sm png-red" data-on="true"></span></span><span class="png-name">未読の通知 3件</span></li>
</ul>
<button type="button" class="png-btn" id="png-btn">オフラインにする</button>
</div>
.png-stage { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1.2rem; padding:2rem 1.2rem; background:#0B0B10; min-height:280px; }
.png-list { list-style:none; margin:0; padding:0; width:100%; max-width:300px; display:flex; flex-direction:column; gap:.6rem; }
.png-row { display:flex; align-items:center; gap:.75rem; padding:.7rem .9rem; border-radius:12px; background:#15151B; border:1px solid rgba(255,255,255,.08); color:#EDEDED; font-size:.85rem; }
.png-name { flex:1; min-width:0; }
.png-badge { padding:.15rem .5rem; border-radius:6px; background:#DC2626; color:#fff; font-family:'Oswald',sans-serif; font-size:.7rem; letter-spacing:.12em; }
.png-state { color:#34D399; font-size:.74rem; }
.png-state.is-off { color:#A1A1AA; }
.png-dot { --png-c:#34D399; position:relative; display:inline-block; flex:0 0 auto; width:12px; height:12px; border-radius:50%; background:var(--png-c); }
.png-dot::before { content:''; position:absolute; inset:0; border-radius:inherit; background:var(--png-c); opacity:.75; animation: png-ping 1s cubic-bezier(0,0,.2,1) infinite; }
.png-red { --png-c:#F43F5E; }
.png-dot[data-on="false"] { --png-c:#6B7280; }
.png-dot[data-on="false"]::before { animation:none; opacity:0; }
.png-dot-sm { position:absolute; top:-2px; right:-2px; width:10px; height:10px; box-shadow:0 0 0 2px #15151B; }
.png-avatar, .png-bell { position:relative; flex:0 0 32px; height:32px; border-radius:50%; display:flex; align-items:center; justify-content:center; background:#7B37A8; color:#fff; font-family:'Oswald',sans-serif; font-size:.85rem; }
.png-bell { background:#1E1E26; font-size:1rem; }
.png-btn { min-height:44px; padding:0 1.2rem; border-radius:999px; border:1px solid rgba(255,255,255,.2); background:transparent; color:#EDEDED; font-size:.84rem; cursor:pointer; }
.png-btn:focus-visible { outline:2px solid #E91B89; outline-offset:2px; }
@keyframes png-ping { 75%, 100% { transform:scale(2); opacity:0; } }
@media (prefers-reduced-motion: reduce) {
.png-dot::before { animation:none; opacity:0; }
}
(function(){
var btn = document.getElementById('png-btn');
var state = document.getElementById('png-state');
var dot = document.querySelector('.png-avatar .png-dot');
if (!btn || !state || !dot) return;
btn.addEventListener('click', function(){
var on = dot.dataset.on !== 'true';
dot.dataset.on = on ? 'true' : 'false';
state.textContent = on ? 'オンライン' : 'オフライン';
state.classList.toggle('is-off', !on);
btn.textContent = on ? 'オフラインにする' : 'オンラインにする';
});
})();
Tailwind CSS の animate-ping を使う場合の書き方(公式ドキュメントの用例と同じ組み立て)。motion-reduce:animate-none で動きを減らす設定の時は止めます。
<span class="relative flex size-3"> <span class="absolute inline-flex h-full w-full animate-ping rounded-full bg-emerald-400 opacity-75 motion-reduce:animate-none"></span> <span class="relative inline-flex size-3 rounded-full bg-emerald-500"></span> </span>
AI PROMPT
オンライン中・配信中・未読ありを示す小さな点から、波紋が広がり続けるステータス表示(Tailwind CSS の animate-ping と同じ動き)を素のCSSで作って。点は幅と高さ12px・border-radius:50% で、色はカスタムプロパティ --png-c に持たせる。::before を inset:0 で点に重ね、同じ色・不透明度 .75 にして、@keyframes で 75% と 100% の時点を transform: scale(2)・opacity:0 にする(0% は書かない=元の大きさから始まる)。時間は 1s、イージングは cubic-bezier(0, 0, .2, 1)、無限ループ(animate-ping と同じ指定)。使い方の例を3行作る:配信中(赤い点+「LIVE」のバッジ)、ユーザーのオンライン表示(丸いアバターの右上に小さい点を重ね、周りに背景色の box-shadow で縁取り)、通知(ベルのアイコンの右上に赤い点)。ボタンでオンラインとオフラインを切り替え、オフラインでは点を灰色にして波紋を止め、横の文字も「オフライン」に変える(色だけでなく文字でも状態を示す)。点そのものは aria-hidden="true" にする。@media (prefers-reduced-motion: reduce) では波紋を止める。Tailwind CSS を使う場合の書き方(animate-ping と motion-reduce:animate-none)も併記する。 Acceptance criteria: works with prefers-reduced-motion (animation disabled), zero console errors, zero layout shift
AIエージェントでの実装ガイド → Claude Code でWebアニメーションを実装する
BOOKS · PR · AMAZON
※当サイトはAmazonアソシエイトプログラムの参加者です。リンクから商品をご購入いただくと、当方に紹介料が発生します。
学びを止めない · AMAZONサブスク
※当サイトはAmazonアソシエイトプログラムの参加者です。リンクから商品をご購入いただくと、当方に紹介料が発生します。
オンライン中・配信中・未読の通知ありといった状態を示す小さな点から、波紋のような輪が広がり続ける表示です。Tailwind CSS にはこの動きを1つのクラスで付けられる animate-ping というユーティリティがあり、公式ドキュメントでは通知バッジなどに使える動きとして紹介されています。
当サイトの Tailwind Pulse CTA は同じ animate-ping の波紋をボタンの後ろに広げるCTA、Badge Bounce は数値が変わるたびにバッジが弾む通知、Pulsating Button はボタンの外側に輪が広がる演出です。本ページはアバターやアイコンの隅に置く小さなステータスの点に特化した別テーマで、オンライン・オフラインの切り替えも含めて扱います。
波紋は小さくても目を引くため、画面の中で使う場所を絞るほど効果が上がります。常に動き続ける表示なので、動きを減らす設定の利用者には止め、状態は色と文字の両方で伝えてください。
Tailwind の animate-ping と同じ動きですか?
はい。Tailwind CSS の公式ドキュメントでは animate-ping を「ping 1s cubic-bezier(0, 0, 0.2, 1) infinite」、キーフレームを「75%, 100% で scale(2)・opacity: 0」と定義しており、本ページのCSSはこれと同じ値で書いています。Tailwind を使っているプロジェクトなら、併記した TAILWIND のコードのようにクラスを並べるだけで同じ表示になります。
点の色だけで状態を伝えてもよいですか?
色の見分けにくい人や読み上げの利用者には、点の色だけでは状態が伝わりません。本実装はオンライン・オフラインを横の文字でも示し、点自体は装飾として aria-hidden にしています。波紋は注意を引く動きなので、配信中や未読など「今すぐ見てほしい」状態に絞って使うと効果的です。
コードは無料で使えますか?
はい。Motion LabのコードスニペットとAIプロンプトは、クレジット表記なしで自由に使えます。コピーしてそのままプロジェクトに利用できます。