Marquee

Scroll content continuously in a seamless horizontal loop using a CSS animation.

Marquee is a client component that scrolls its children in a seamless horizontal loop. Use it for logo strips, announcements and testimonials. It repeats the children inside a track and moves the track with a CSS keyframe animation, with no JavaScript animation loop.

Acme
Globex
Initech
Umbrella
Hooli
Stark

Import#

typescript
import { Marquee } from "@reactberry/system/blocks";

Usage#

typescript
import { Marquee } from "@reactberry/system/blocks";
import { Box, Text } from "@reactberry/system/elements";

const partners = ["Acme", "Globex", "Initech", "Umbrella", "Hooli"];

export default function PartnerStrip() {
  return (
    <Marquee speed={40} gap="2rem" pauseOnHover>
      {partners.map((name) => (
        <Box key={name} px="m" py="s" skin="surface" shape="pill">
          <Text>{name}</Text>
        </Box>
      ))}
    </Marquee>
  );
}

Examples#

Short announcement#

Set repeat higher when the content is narrower than the marquee. Here direction="right" reverses the scroll and fadeEdges={false} removes the edge fade.

Free delivery on orders over £50

Pause on hover#

Use pauseOnHover and a lower speed for content people need to read, such as quotes.

“Setup took five minutes.”Maya
“Support replied within the hour.”Tom
“The reports save us a day each month.”Priya

API#

Marquee#

PropTypeDefaultDescription
children*
ReactNode
—

Content to repeat. Rendered once per copy inside a flex row.

speed
number
50

Relative speed. One loop lasts 20 * (100 / speed) seconds, so higher values scroll faster.

direction
"left""right"
"left"

Scroll direction. "right" reverses the animation.

pauseOnHover
boolean
false

Pauses the animation while the pointer is over the marquee.

gap
string | number
1rem

Space between items, also applied as right padding on each copy so the loop seam matches.

repeat
number
2

Number of copies rendered. Values below 2 are raised to 2.

fadeEdges
boolean
true

Fades the content out over the outer 10% on each side with a mask.

className
string
—

Class name applied to the root element.

No other props are accepted and nothing is spread.

Accessibility#

  • Every copy after the first has aria-hidden set, so screen readers encounter the content once.
  • The animation runs indefinitely and has no prefers-reduced-motion handling. Use pauseOnHover, or render static content where motion should be avoided.

Notes#

  • With the default speed of 50, one loop lasts 40 seconds.
  • Each copy of the content must be at least as wide as the marquee for the loop to appear seamless. Increase repeat when the content is short.
  • The root is position: relative, width: 100%, and clips overflow.