Marquee
RzMarquee is a CSS-only, SSR-safe infinite scrolling primitive for arbitrary Razor content. It duplicates segments on the server and animates those strips with theme utilities, so you can compose card rails, vertical feeds, logo bands, and perspective effects without introducing Blazor interactivity.
Under the Hood
RzMarquee renders repeated segments during SSR. The first segment remains interactive, while clones are emitted with aria-hidden="true" and inert. Motion comes from CSS keyframes and custom properties, not Alpine.
Basic Usage
This follows the core two-row testimonial pattern: one marquee in the default direction and a second in reverse, with edge fades supplied by outer composition.
<div class="relative overflow-hidden rounded-xl border p-2">
<RzMarquee PauseOnHover Duration="20s">
<figure class="w-64 shrink-0 rounded-xl border bg-muted/40 p-4">...</figure>
<figure class="w-64 shrink-0 rounded-xl border bg-muted/40 p-4">...</figure>
<figure class="w-64 shrink-0 rounded-xl border bg-muted/40 p-4">...</figure>
</RzMarquee>
<RzMarquee PauseOnHover Reverse Duration="20s">
<figure class="w-64 shrink-0 rounded-xl border bg-muted/40 p-4">...</figure>
<figure class="w-64 shrink-0 rounded-xl border bg-muted/40 p-4">...</figure>
<figure class="w-64 shrink-0 rounded-xl border bg-muted/40 p-4">...</figure>
</RzMarquee>
</div>Vertical Marquee
Vertical marquees need a bounded height. This composition mirrors the original vertical demo by pairing two opposite columns inside a masked container.
<div class="relative h-[28rem] overflow-hidden rounded-xl border p-3">
<RzMarquee Orientation="MarqueeOrientation.Vertical" PauseOnHover Duration="20s" class="h-full">...</RzMarquee>
<RzMarquee Orientation="MarqueeOrientation.Vertical" PauseOnHover Reverse Duration="20s" class="h-full">...</RzMarquee>
</div>Logo Cloud
The marquee primitive intentionally avoids visual styling concerns. This logo rail shows how spacing, fades, and outer container treatment are handled by consumers.
<RzMarquee Gap="3rem" Duration="24s">
<img src="..." alt="Microsoft" class="size-14 shrink-0" />
<img src="..." alt="Apple" class="size-14 shrink-0" />
<img src="..." alt="Google" class="size-14 shrink-0" />
</RzMarquee>3D Perspective
Perspective transformations are a parent-layout concern. This demo recreates the signature 3D wall by nesting four vertical marquees in a transformed wrapper.
<div class="relative h-96 overflow-hidden [perspective:300px]">
<div class="flex gap-4" style="transform:translateX(-100px) translateZ(-100px) rotateX(20deg) rotateY(-10deg) rotateZ(20deg);">
<RzMarquee Orientation="MarqueeOrientation.Vertical" PauseOnHover Duration="20s">...</RzMarquee>
<RzMarquee Orientation="MarqueeOrientation.Vertical" PauseOnHover Reverse Duration="20s">...</RzMarquee>
<RzMarquee Orientation="MarqueeOrientation.Vertical" PauseOnHover Reverse Duration="20s">...</RzMarquee>
<RzMarquee Orientation="MarqueeOrientation.Vertical" PauseOnHover Duration="20s">...</RzMarquee>
</div>
</div>Interactive Child Content and Accessibility
Focusable children remain usable in the first segment while cloned segments are hidden from assistive technologies and excluded from tab order. Pair this with PauseOnHover so keyboard users can pause motion via focus-within.
<RzMarquee PauseOnHover Duration="22s" aria-label="Quick actions">
<a href="/docs">Read docs</a>
<a href="/release-notes">Release notes</a>
<a href="/status">System status</a>
</RzMarquee>Component Parameters
| Property | Description | Type | Default |
|---|---|---|---|
Orientation | Selects horizontal or vertical motion. | MarqueeOrientation | MarqueeOrientation.Horizontal |
Reverse | Reverses animation direction. | bool | false |
PauseOnHover | Pauses animation on hover and focus-within. | bool | false |
Repeat | Number of rendered segments. Values lower than 2 are clamped when content exists. | int | 4 |
Duration | CSS duration for one full segment cycle. | string | "40s" |
Gap | CSS gap between child items and repeated segments. | string | "1rem" |
ChildContent | Logical segment content repeated by the marquee. | RenderFragment? | null |
Interoperability
RzMarquee does not expose an Alpine API. It emits no x-data, no data-alpine-root, and no component asset dependencies. Pass-through attributes support HTMX patterns, and the root emits data-orientation, data-reverse, and data-pauses-on-hover markers for diagnostics and tests.