DEMO
CODE
<div class="demo-stage imc-stage">
<div class="imc-viewport">
<div class="imc-track">
<figure class="imc-card"><blockquote>“導入して2週間で問い合わせが1.8倍になりました。”</blockquote><figcaption>— A社 マーケ担当</figcaption></figure>
<figure class="imc-card"><blockquote>“実装が驚くほど早い。コピペで動くのが助かる。”</blockquote><figcaption>— B社 フロントエンド</figcaption></figure>
<figure class="imc-card"><blockquote>“デザイナーと認識を合わせる時間が半分になった。”</blockquote><figcaption>— C社 PM</figcaption></figure>
<figure class="imc-card"><blockquote>“AIへの指示文がそのまま載っているのが最高。”</blockquote><figcaption>— D社 個人開発</figcaption></figure>
<figure class="imc-card" aria-hidden="true"><blockquote>“導入して2週間で問い合わせが1.8倍になりました。”</blockquote><figcaption>— A社 マーケ担当</figcaption></figure>
<figure class="imc-card" aria-hidden="true"><blockquote>“実装が驚くほど早い。コピペで動くのが助かる。”</blockquote><figcaption>— B社 フロントエンド</figcaption></figure>
<figure class="imc-card" aria-hidden="true"><blockquote>“デザイナーと認識を合わせる時間が半分になった。”</blockquote><figcaption>— C社 PM</figcaption></figure>
<figure class="imc-card" aria-hidden="true"><blockquote>“AIへの指示文がそのまま載っているのが最高。”</blockquote><figcaption>— D社 個人開発</figcaption></figure>
</div>
</div>
</div>
.imc-stage { display:flex; align-items:center; justify-content:center; padding:2rem 0; background:#0B0B10; min-height:280px; overflow:hidden; }
.imc-viewport {
width:100%; overflow:hidden;
-webkit-mask-image:linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
mask-image:linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.imc-track {
display:flex; gap:1rem; width:max-content;
animation: imc-scroll 26s linear infinite;
}
.imc-viewport:hover .imc-track { animation-play-state:paused; }
.imc-card {
flex:0 0 260px; margin:0; padding:1.4rem 1.5rem; border-radius:14px;
background:#17171C; border:1px solid rgba(255,255,255,.09);
}
.imc-card blockquote { margin:0 0 .9rem; font-size:.84rem; line-height:1.8; color:#E4E4EA; }
.imc-card figcaption { font-family:'JetBrains Mono',monospace; font-size:.66rem; letter-spacing:.06em; color:#E91B89; }
@keyframes imc-scroll {
from { transform:translateX(0); }
to { transform:translateX(calc(-50% - .5rem)); }
}
@media (prefers-reduced-motion: reduce) {
.imc-track { animation:none; }
}
AI PROMPT
お客様の声カードが途切れず横に流れ続ける無限カルーセルをCSSだけで作って。要点は「同じカード列を2セット並べ、1セットぶんだけ移動させて折り返す」こと。トラックは display: flex; width: max-content; gap: 1rem とし、@keyframes で transform: translateX(0) から translateX(calc(-50% - gapの半分)) まで linear で無限ループする。-50% だけだと gap のぶんズレて継ぎ目が見えるので、gap の半分を引くのが継ぎ目を消すコツ。複製した2セット目には aria-hidden="true" を付けて読み上げの重複を防ぐ。両端はビューポートに mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent) を掛けると、カードが切れずに溶けて消える(-webkit-mask-image も併記)。ホバーで animation-play-state: paused にすると本文を読める。速度は 1セットのカード枚数 × 6〜7秒 を目安に animation-duration で調整する。 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アソシエイトプログラムの参加者です。リンクから商品をご購入いただくと、当方に紹介料が発生します。
同じカード列を2セット並べ、1セットぶんだけ移動させて折り返すことで、途切れなく流れ続けるように見せる手法です。Aceternity UI の Infinite Moving Cards として知られ、お客様の声・レビュー・実績ロゴの帯として定番になっています。
当サイトの Logo Marquee は高さの揃ったロゴ画像を流す帯、Marquee Text は1行のテキストを流す表現です。本ページは「中身のあるカードを流す」別テーマで、1枚あたりの情報量が多いぶん、ホバーで停止できることが実用上ほぼ必須になります。
継ぎ目が見える不具合の原因はほぼ gap の計算漏れです。移動量から gap の半分を引くこと、そして複製側に aria-hidden を付けることの2点を押さえてください。
継ぎ目が見えてしまうのはなぜですか?
移動量が1セットぶんと一致していないためです。gap がある場合、translateX(-50%) では gap の半分だけズレが生じます。translateX(calc(-50% - gapの半分)) にすると、2セット目の先頭が1セット目の先頭と正確に重なり、継ぎ目が消えます。カード幅が不揃いでも、2セット並べる方式ならこの計算で成立します。
スクリーンリーダーで内容が2回読まれます。
複製したセットに aria-hidden="true" を付けてください。無限スクロールは視覚的な演出として同じ内容を2セット必要としますが、読み上げには1セットで十分です。本ページのコードでは後半4枚に aria-hidden を付けています。
コードは無料で使えますか?
はい。Motion LabのコードスニペットとAIプロンプトは、クレジット表記なしで自由に使えます。コピーしてそのままプロジェクトに利用できます。