Mantine Marquee

Logo

@gfazioli/mantine-marquee

A Mantine component that allows you to create a marquee effect with a list of elements.

Installation

yarn add @gfazioli/mantine-marquee

After installation import package styles at the root of your application:

import '@gfazioli/mantine-marquee/styles.css';

You can import styles within a layer @layer mantine-marquee by importing @gfazioli/mantine-marquee/styles.layer.css file.

import '@gfazioli/mantine-marquee/styles.layer.css';

Usage

The Marquee component allows you to create a marquee effect with any content.

Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #5
Hope you like it #6
Have a nice day #7
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #5
Hope you like it #6
Have a nice day #7
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #5
Hope you like it #6
Have a nice day #7
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #5
Hope you like it #6
Have a nice day #7
Repeat
Duration
Gap
Fade edges size
Fade edges size y
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <Marquee repeat={4} duration={10} gap="sm" fadeEdgesSize={20}>
      <BoxComponent bg="red">Hello World #1</BoxComponent>
      <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
      <BoxComponent bg="blue">Have a nice day #3</BoxComponent>
      <BoxComponent bg="lime">Goodbye #4</BoxComponent>
    </Marquee>
  );
}

Fade edges

The fadeEdges prop adds a smooth fade effect at the edges of the scroll area using CSS mask-image. It accepts true, "linear", "ellipse", or "rect" — passing true is equivalent to "linear". Use fadeEdgesSize to control how much of the edge is faded ("xs" | "sm" | "md" | "lg" | "xl" or a percentage string).

Linear

fadeEdges="linear" applies a gradient mask on the leading and trailing scroll edges. This works for both horizontal and vertical layouts, and it is ideal for content that enters and exits from the sides.

Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box, Flex } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <Flex direction="column" gap="md">
      <Marquee fadeEdges="linear" fadeEdgesSize="sm">
        <BoxComponent bg="blue">Hello World #1</BoxComponent>
        <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
        <BoxComponent bg="indigo">Have a nice day #3</BoxComponent>
        <BoxComponent bg="teal">Goodbye #4</BoxComponent>
      </Marquee>
      <Marquee fadeEdges="linear" fadeEdgesSize="sm" reverse>
        <BoxComponent bg="orange">Hello World #1</BoxComponent>
        <BoxComponent bg="red">Hope you like it #2</BoxComponent>
        <BoxComponent bg="pink">Have a nice day #3</BoxComponent>
        <BoxComponent bg="grape">Goodbye #4</BoxComponent>
      </Marquee>
    </Flex>
  );
}

Ellipse

fadeEdges="ellipse" applies a radial elliptical mask that fades all around the border. This is orientation-independent — it works identically for horizontal and vertical marquees. It is particularly effective for logo carousels, icon showcases, or any content where a vignette effect is desired.

import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { ThemeIcon } from '@mantine/core';
import {
  IconBrand4chan,
  IconBrandAmazon,
  IconBrandBing,
  IconBrandGithub,
  IconBrandMantine,
  IconBrandWhatsapp,
  IconBrandWordpress,
} from '@tabler/icons-react';

function Demo() {
  const iconsBrand = [
    <IconBrand4chan style={{ width: '70%', height: '70%' }} />,
    <IconBrandWhatsapp style={{ width: '70%', height: '70%' }} />,
    <IconBrandWordpress style={{ width: '70%', height: '70%' }} />,
    <IconBrandBing style={{ width: '70%', height: '70%' }} />,
    <IconBrandGithub style={{ width: '70%', height: '70%' }} />,
    <IconBrandMantine style={{ width: '70%', height: '70%' }} />,
    <IconBrandAmazon style={{ width: '70%', height: '70%' }} />,
  ];

  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <ThemeIcon {...props} variant="transparent" size="120px">
        {children}
      </ThemeIcon>
    );
  }

  return (
    <Marquee pauseOnHover fadeEdges="ellipse" fadeEdgesSize="md">
      {iconsBrand.map((icon, index) => (
        <BoxComponent key={index}>{icon}</BoxComponent>
      ))}
    </Marquee>
  );
}

Circle

Since the ellipse mask uses radial-gradient(ellipse closest-side), applying fadeEdges="ellipse" to a square element (w and h are equal) produces a perfectly circular mask. No additional prop is needed — the geometry does the work.

John Doe

Jane Doe

Jessica Doe

Jack Doe

Jill Doe

John Doe

Jane Doe

Jessica Doe

Jack Doe

Jill Doe

import { Marquee } from '@gfazioli/mantine-marquee';
import { Avatar, Card, Center, Rating, Stack, Text } from '@mantine/core';

function Demo() {
  const testimonials = [
    { name: 'John Doe', avatar: '...', rating: 4 },
    { name: 'Jane Doe', avatar: '...', rating: 4 },
    { name: 'Jessica Doe', avatar: '...', rating: 2 },
    { name: 'Jack Doe', avatar: '...', rating: 5 },
    { name: 'Jill Doe', avatar: '...', rating: 3 },
  ];

  return (
    <Center>
      {/* Ellipse on a square element (w=h) produces a circular mask */}
      <Marquee
        w={300}
        h={300}
        pauseOnHover
        fadeEdges="ellipse"
        fadeEdgesSize="md"
        style={{ justifyContent: 'center' }}
      >
        {testimonials.map((t, index) => (
          <Card key={index} w={120} shadow="sm" padding="sm" radius="md" withBorder>
            <Stack align="center" gap="xs">
              <Avatar size="lg" radius="xl" src={t.avatar} />
              <Text size="xs" fw={600} ta="center">
                {t.name}
              </Text>
              <Rating value={t.rating} size="xs" />
            </Stack>
          </Card>
        ))}
      </Marquee>
    </Center>
  );
}

Rect

fadeEdges="rect" uses two intersected linear gradients (mask-composite: intersect) to fade all 4 edges independently. The horizontal gradient controls left/right, the vertical gradient controls top/bottom — at the corners the alpha values multiply naturally, creating a smooth diagonal falloff.

fadeEdgesSize accepts a [horizontal, vertical] tuple for independent axis control. For example fadeEdgesSize={['lg', 'xs']} applies a large fade on left/right and a small fade on top/bottom.

Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box, Flex } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <Flex direction="column" gap="md">
      {/* Uniform fade on all 4 edges */}
      <Marquee fadeEdges="rect" fadeEdgesSize="md" h={60}>
        <BoxComponent bg="blue">Hello World #1</BoxComponent>
        <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
        <BoxComponent bg="indigo">Have a nice day #3</BoxComponent>
        <BoxComponent bg="teal">Goodbye #4</BoxComponent>
      </Marquee>
      {/* Tuple: more fade on left/right (lg), less on top/bottom (xs) */}
      <Marquee fadeEdges="rect" fadeEdgesSize={['lg', 'xs']} reverse h={60}>
        <BoxComponent bg="orange">Hello World #1</BoxComponent>
        <BoxComponent bg="red">Hope you like it #2</BoxComponent>
        <BoxComponent bg="pink">Have a nice day #3</BoxComponent>
        <BoxComponent bg="grape">Goodbye #4</BoxComponent>
      </Marquee>
    </Flex>
  );
}

Multiple

The Marquee component allows you to create a marquee effect with multiple items.

Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <>
      <Marquee mb={16} fadeEdges>
        <BoxComponent bg="red">Hello World #1</BoxComponent>
        <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
        <BoxComponent bg="blue">Have a nice day #3</BoxComponent>
        <BoxComponent bg="lime">Goodbye #4</BoxComponent>
      </Marquee>
      <Marquee reverse fadeEdges>
        <BoxComponent bg="red">Hello World #1</BoxComponent>
        <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
        <BoxComponent bg="blue">Have a nice day #3</BoxComponent>
        <BoxComponent bg="lime">Goodbye #4</BoxComponent>
      </Marquee>
    </>
  );
}

Vertical

The Marquee component allows you to create a marquee effect with multiple items in vertical direction.

Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box, Flex } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <Flex w={500}>
      <Marquee h={300} fadeEdges vertical>
        <BoxComponent bg="red">Hello World #1</BoxComponent>
        <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
        <BoxComponent bg="blue">Have a nice day #3</BoxComponent>
        <BoxComponent bg="lime">Goodbye #4</BoxComponent>
      </Marquee>
      <Marquee h={300} reverse fadeEdges vertical>
        <BoxComponent bg="red">Hello World #1</BoxComponent>
        <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
        <BoxComponent bg="blue">Have a nice day #3</BoxComponent>
        <BoxComponent bg="lime">Goodbye #4</BoxComponent>
      </Marquee>
    </Flex>
  );
}

Responsive vertical

The vertical prop accepts a responsive breakpoint object in addition to a plain boolean. This lets you switch between vertical and horizontal layouts at different viewport widths using Mantine's useMatches hook under the hood.

// Vertical on mobile, horizontal from md breakpoint up
<Marquee vertical={{ base: true, md: false }}>{/* ... */}</Marquee>
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <Marquee vertical={{ base: true, md: false }} h={300} fadeEdges>
      <BoxComponent bg="blue">Hello World #1</BoxComponent>
      <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
      <BoxComponent bg="indigo">Have a nice day #3</BoxComponent>
      <BoxComponent bg="teal">Goodbye #4</BoxComponent>
    </Marquee>
  );
}

Responsive gap

The gap prop also accepts a responsive breakpoint object. This is useful when switching layout direction at a breakpoint — you can pair it with a different gap size.

// Small gap on mobile, large gap from md breakpoint up
<Marquee gap={{ base: 'xs', md: 'xl' }}>{/* ... */}</Marquee>
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
Hello World #1
Hope you like it #2
Have a nice day #3
Goodbye #4
import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { Box } from '@mantine/core';

function Demo() {
  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <Box {...props} p="md" w="200px" c="white" style={{ borderRadius: '8px' }}>
        {children}
      </Box>
    );
  }

  return (
    <Marquee gap={{ base: 'xs', md: 'xl' }} fadeEdges="linear" w="100%">
      <BoxComponent bg="blue">Hello World #1</BoxComponent>
      <BoxComponent bg="cyan">Hope you like it #2</BoxComponent>
      <BoxComponent bg="indigo">Have a nice day #3</BoxComponent>
      <BoxComponent bg="teal">Goodbye #4</BoxComponent>
    </Marquee>
  );
}

Example: Testimonials

Your customers feedback is important to you. Use Marquee to display your testimonials.

John Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jane Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jessica Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jack Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jill Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

John Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jane Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jessica Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jack Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Jill Doe

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

import { Marquee } from '@gfazioli/mantine-marquee';
import { Avatar, Card, Group, Rating, Stack, Text, Title } from '@mantine/core';
import { ReactNode } from 'react';
import { testimonials } from './testimonials';

function Demo() {
  function BoxComponent({
    children,
    avatar,
    name,
    rating,
    ...props
  }: {
    children: ReactNode;
    avatar: string;
    name: string;
    [key: string]: any;
  }) {
    return (
      <Card w={200} shadow="sm" padding="lg" radius="md" withBorder>
        <Card.Section p="md">
          <Group>
            <Avatar size="md" radius="xl" src={avatar} />
            <Title order={4}>{name}</Title>
          </Group>
        </Card.Section>
        <Stack>
          <Text size="sm" c="dimmed">
            {children}
          </Text>
          <Group justify="end">
            <Rating value={rating} />
          </Group>
        </Stack>
      </Card>
    );
  }

  return (
    <Marquee pauseOnHover fadeEdges>
      {testimonials.map(({ text, ...testimonial }, index) => (
        <BoxComponent key={index} {...testimonial}>
          {text}
        </BoxComponent>
      ))}
    </Marquee>
  );
}

Example: Branding

One of the most common use cases for Marquee is to create branding banners.

import { ReactNode } from 'react';
import { Marquee } from '@gfazioli/mantine-marquee';
import { ThemeIcon } from '@mantine/core';
import {
  IconBrand4chan,
  IconBrandAmazon,
  IconBrandBing,
  IconBrandGithub,
  IconBrandMantine,
  IconBrandWhatsapp,
  IconBrandWordpress,
} from "@tabler/icons-react";

function Demo() {
  const iconsBrand = [
    <IconBrand4chan style={{ width: '70%', height: '70%' }} />,
    <IconBrandWhatsapp style={{ width: '70%', height: '70%' }} />,
    <IconBrandWordpress style={{ width: '70%', height: '70%' }} />,
    <IconBrandBing style={{ width: '70%', height: '70%' }} />,
    <IconBrandGithub style={{ width: '70%', height: '70%' }} />,
    <IconBrandMantine style={{ width: '70%', height: '70%' }} />,
    <IconBrandAmazon style={{ width: '70%', height: '70%' }} />,
  ];

  function BoxComponent({ children, ...props }: { children: ReactNode; [key: string]: any }) {
    return (
      <ThemeIcon {...props} variant="transparent" size="120px">
        {children}
      </ThemeIcon>
    );
  }

  return (
    <Marquee pauseOnHover fadeEdges>
      {iconsBrand.map((icon, index) => (
        <BoxComponent key={index}>{icon}</BoxComponent>
      ))}
    </Marquee>
  );
}