Skip to content

Marquee

A customizable scrolling component that loops its content horizontally or vertically, with configurable direction, hover pause, and repeat options.

Jack@jack

I've never seen anything like this before. It's amazing. I love it.

Jack@jack

I've never seen anything like this before. It's amazing. I love it.

Jack@jack

I've never seen anything like this before. It's amazing. I love it.

Jack@jack

I've never seen anything like this before. It's amazing. I love it.

Jill@jill

I don't know what to say. I'm speechless. This is amazing.

John@john

I'm at a loss for words. This is amazing. I love it.

Jill@jill

I don't know what to say. I'm speechless. This is amazing.

John@john

I'm at a loss for words. This is amazing. I love it.

Jill@jill

I don't know what to say. I'm speechless. This is amazing.

John@john

I'm at a loss for words. This is amazing. I love it.

Jill@jill

I don't know what to say. I'm speechless. This is amazing.

John@john

I'm at a loss for words. This is amazing. I love it.

Installation

Copy and paste the following code into your project:

vue
<script setup lang='ts'>
import { cn } from '@/lib/utils'

interface MarqueeProps {
  class?: string
  reverse?: boolean
  pauseOnHover?: boolean
  vertical?: boolean
  repeat?: number
  [key: string]: any
};

const props = withDefaults(defineProps<MarqueeProps>(), {
  pauseOnHover: false,
  vertical: false,
  repeat: 4,
})

const className = cn(
  'flex shrink-0 justify-around [gap:var(--gap)]',
  {
    'animate-marquee-vertical flex-col': props.vertical,
    'animate-marquee flex-row': !props.vertical,
    '[animation-direction:reverse]': props.reverse,
    'group-hover:[animation-play-state:paused]': props.pauseOnHover,
  },
)
</script>

<template>
  <div
    v-bind="props" :class="cn('group flex overflow-hidden p-2 [--duration:40s] [--gap:1rem] [gap:var(--gap)]',
                              {
                                'flex-row': !props.vertical,
                                'flex-col': props.vertical,
                              },
                              props.class,
    )"
  >
    <div v-for="i in Array(props.repeat).fill(0)" :key="i">
      <div :key="i" :class="className">
        <slot />
      </div>
    </div>
  </div>
</template>
vue
<script setup lang='ts'>
import { cn } from '@/lib/utils'

const props = defineProps<{
  img: string
  name: string
  username: string
  body: string
}>()
</script>

<template>
  <div
    :class="cn(
      'relative w-64 cursor-pointer overflow-hidden h-36 flex flex-col space-y-1 rounded-xl px-4',
      '  border-gray-950/[.1] bg-gray-950/[.01] border-parent hover:bg-gray-950/[.05]',
    )"
  >
    <div class="flex items-center space-x-2">
      <img class="rounded-full" width="32" height="32" :src="props.img">
      <p class="flex flex-col space-y-1">
        <span class="text-sm font-medium dark:text-white">
          {{ props.name }}
        </span>
        <span class="text-xs font-medium dark:text-white/40">
          {{ props.username }}
        </span>
      </p>
    </div>

    <div>
      <span leading-none class="text-sm font-medium  dark:text-white/40">
        {{ props.body }}
      </span>
    </div>
  </div>
</template>

<style scoped>
.border-parent {
  border: 1px solid #ecedee;
}
</style>

Add the following animations to your tailwind.config.js file:

tailwind.config.js
js
module.exports = {
  theme: {
    extend: {
      animation: {
        'marquee': 'marquee var(--duration) linear infinite',
        'marquee-vertical': 'marquee-vertical var(--duration) linear infinite',
      },
      keyframes: {
        'marquee': {
          from: { transform: 'translateX(0)' },
          to: { transform: 'translateX(calc(-100% - var(--gap)))' },
        },
        'marquee-vertical': {
          from: { transform: 'translateY(0)' },
          to: { transform: 'translateY(calc(-100% - var(--gap)))' },
        },
      },
    },
  },
}

Examples

Vertical Marquee

Jack@jack

I've never seen anything like this before. It's amazing. I love it.

Jack@jack

I've never seen anything like this before. It's amazing. I love it.

Jack@jack

I've never seen anything like this before. It's amazing. I love it.

Jack@jack

I've never seen anything like this before. It's amazing. I love it.

Jill@jill

I don't know what to say. I'm speechless. This is amazing.

John@john

I'm at a loss for words. This is amazing. I love it.

Jill@jill

I don't know what to say. I'm speechless. This is amazing.

John@john

I'm at a loss for words. This is amazing. I love it.

Jill@jill

I don't know what to say. I'm speechless. This is amazing.

John@john

I'm at a loss for words. This is amazing. I love it.

Jill@jill

I don't know what to say. I'm speechless. This is amazing.

John@john

I'm at a loss for words. This is amazing. I love it.

3D Marquee

Props

PropTypeDefaultDescription
classstringThe class to apply to the component.
reversebooleanfalseWhether or not to reverse the direction of the marquee.
pauseOnHoverbooleanfalseWhether or not to pause the marquee when the user hovers over the component.
verticalbooleanfalseWhether or not to display the marquee vertically.
repeatnumber1The number of times to repeat the content.

Released under the MIT License.