Skip to content

Components

An Infinite Logo Ticker in Pure CSS — Yes Really, No JavaScript

One Keyframe, a Duplicated Track, and the Seam Nobody Notices Until It Jumps
Written by Aiden Wood Founder and Lead Design Engineer
♾️ 🎞️ 🪶

The "trusted by" logo strip is on every B2B landing page in existence, and an alarming number of them ship a carousel library to make it drift sideways. That's a JavaScript dependency, main-thread animation work, and a layout-shift risk — for logos that scroll.

The whole effect is one CSS keyframe. Velocity X's logo-ticker is a free, MIT-licensed .astro component built on exactly this pattern — install it and read the whole thing in a minute.

The Money Pattern

<div class="overflow-hidden">
  <div class="flex w-max gap-12 animate-[ticker_30s_linear_infinite]">
    <ul class="flex shrink-0 gap-12">…logos…</ul>
    <ul class="flex shrink-0 gap-12" aria-hidden="true">…same logos…</ul>
  </div>
</div>

@keyframes ticker {
  to { transform: translateX(-50%); }
}

Two identical tracks sit side by side; the animation slides the pair exactly one track-width (−50%) and loops. Frame 0 and frame N are pixel-identical, so the loop point is invisible. The compositor runs the transform off the main thread — it stays smooth while your JS bundle is still parsing.

The Catch

Three details separate this from the janky version. First, the seam: -50% is only seamless if the duplicate is exactly identical — same gap before the first logo as after the last, which is why the gap lives on the track, not as track padding.

Second, w-max on the moving element. Without it the flex container clamps to the viewport and the percentage translates against the wrong width — the classic "my ticker jumps" bug.

Third, the duplicate track is aria-hidden and the whole strip respects prefers-reduced-motion — a permanently moving element is an accessibility failure, not a vibe. Wrap the animation in a motion-safe: variant and the reduced-motion version is just a static logo row.

The Verdict

Spoiler: the library version renders the same pixels with ~30KB more JavaScript. This is the pattern across the free tier of Velocity X — 40 MIT components, CSS doing the work wherever CSS can. The free tier's source is public on GitHub — no account, no key (the velocityx CLI is in preview, not on npm yet).

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.