The announcement bar is always an afterthought — marketing asks for it on Thursday, it ships Friday, and suddenly every page pushes its content down 40px after first paint. That's textbook Cumulative Layout Shift, it's measured by Core Web Vitals, and it costs real ranking on every single page for one strip of text.
Velocity X's announcement-bar-rotator is the no-shift version: a pure .astro component that rotates multiple messages with a CSS animation — no timer JavaScript, no hydration, no jump.
The Money Pattern
Rotation without JS is the same trick as a CSS carousel — stacked messages, a keyframe that steps between them, and a fixed bar height so the page never reflows:
<div class="h-10 overflow-hidden"> <!-- height reserved up front -->
<ul class="animate-[rotate-bar_12s_steps(3)_infinite]">
<li class="h-10 flex items-center justify-center">Free shipping over $100</li>
<li class="h-10 …">40 components free — no account</li>
<li class="h-10 …">v2 launch week</li>
</ul>
</div>
@keyframes rotate-bar {
to { transform: translateY(-300%); } /* one slot per message, steps() snaps */
}
The steps() timing function is the underused hero: it snaps between messages instead of scrolling through them, so three messages share one bar with zero JavaScript. Duplicate the first message at the end of the list and the loop-around is seamless.
The Catch
The height reservation is the entire CLS fix, and it has to be honest on mobile too — a message that wraps to two lines on 320px blows the reserved height. Keep messages short enough to survive the narrowest viewport, or clamp with truncation. Test at 320px, not in the desktop preview.
Rotating content is also a motion and an a11y surface: respect prefers-reduced-motion by showing only the first message, and keep one message per rotation slot readable by duration — 4 seconds per message is the floor, not the target. If every message is critical, that's not a rotator, that's two bars too many.
The Verdict
An announcement bar is a height budget and a keyframe. Reserve the space at build time, rotate with steps(), respect reduced motion — and your Core Web Vitals never know marketing shipped something on Friday. It's in Velocity X's Growth & Conversion category, zero client JS, source you own.









