跑马灯
用法
使用默认插槽和您的内容来创建无限滚动的动画。
<template>
<UMarquee>
<UIcon name="i-simple-icons-github" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-discord" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-x" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-instagram" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-linkedin" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-facebook" class="size-10 shrink-0" />
</UMarquee>
</template>
鼠标悬停时暂停
使用 pause-on-hover
属性,在用户将鼠标悬停在内容上时暂停动画。
<template>
<UMarquee pause-on-hover>
<UIcon name="i-simple-icons-github" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-discord" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-x" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-instagram" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-linkedin" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-facebook" class="size-10 shrink-0" />
</UMarquee>
</template>
反转
使用 reverse
属性来反转动画方向。
<template>
<UMarquee reverse>
<UIcon name="i-simple-icons-github" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-discord" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-x" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-instagram" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-linkedin" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-facebook" class="size-10 shrink-0" />
</UMarquee>
</template>
Orientation
使用 orientation
属性来改变滚动方向。
<template>
<UMarquee orientation="vertical">
<UIcon name="i-simple-icons-github" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-discord" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-x" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-instagram" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-linkedin" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-facebook" class="size-10 shrink-0" />
</UMarquee>
</template>
重复
使用 repeat
属性来指定动画中内容应重复的次数。
<template>
<UMarquee :repeat="6">
<UIcon name="i-simple-icons-github" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-discord" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-x" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-instagram" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-linkedin" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-facebook" class="size-10 shrink-0" />
</UMarquee>
</template>
遮罩层
使用 overlay
属性移除跑马灯边缘的渐变叠加。
<template>
<UMarquee :overlay="false">
<UIcon name="i-simple-icons-github" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-discord" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-x" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-instagram" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-linkedin" class="size-10 shrink-0" />
<UIcon name="i-simple-icons-facebook" class="size-10 shrink-0" />
</UMarquee>
</template>
示例
客户评价
使用 Marquee
组件为您的客户评价创建无限滚动的动画。
Anthony Bettini
VulnCheck 首席执行官兼创始人

Yaz Jallad
Ninjaparade Digital 创始人
Kevin Olson
Fume.app 创始人
Michael Hoffmann
高级前端开发人员
Harlan Wilton
Nuxt 核心团队成员

Thomas Sanlis
自由开发者和设计师

Benjamin Code
YouTube 主播和 SaaS 开发者

Estéban Soubiran
Web 开发者和 UnJS 成员
Anthony Bettini
VulnCheck 首席执行官兼创始人

Yaz Jallad
Ninjaparade Digital 创始人
Kevin Olson
Fume.app 创始人
Michael Hoffmann
高级前端开发人员
Harlan Wilton
Nuxt 核心团队成员

Thomas Sanlis
自由开发者和设计师

Benjamin Code
YouTube 主播和 SaaS 开发者

Estéban Soubiran
Web 开发者和 UnJS 成员
Anthony Bettini
VulnCheck 首席执行官兼创始人

Yaz Jallad
Ninjaparade Digital 创始人
Kevin Olson
Fume.app 创始人
Michael Hoffmann
高级前端开发人员
Harlan Wilton
Nuxt 核心团队成员

Thomas Sanlis
自由开发者和设计师

Benjamin Code
YouTube 主播和 SaaS 开发者

Estéban Soubiran
Web 开发者和 UnJS 成员
Anthony Bettini
VulnCheck 首席执行官兼创始人

Yaz Jallad
Ninjaparade Digital 创始人
Kevin Olson
Fume.app 创始人
Michael Hoffmann
高级前端开发人员
Harlan Wilton
Nuxt 核心团队成员

Thomas Sanlis
自由开发者和设计师

Benjamin Code
YouTube 主播和 SaaS 开发者

Estéban Soubiran
Web 开发者和 UnJS 成员
Anthony Bettini
VulnCheck 首席执行官兼创始人

Yaz Jallad
Ninjaparade Digital 创始人
Kevin Olson
Fume.app 创始人
Michael Hoffmann
高级前端开发人员
Harlan Wilton
Nuxt 核心团队成员

Thomas Sanlis
自由开发者和设计师

Benjamin Code
YouTube 主播和 SaaS 开发者

Estéban Soubiran
Web 开发者和 UnJS 成员
Anthony Bettini
VulnCheck 首席执行官兼创始人

Yaz Jallad
Ninjaparade Digital 创始人
Kevin Olson
Fume.app 创始人
Michael Hoffmann
高级前端开发人员
Harlan Wilton
Nuxt 核心团队成员

Thomas Sanlis
自由开发者和设计师

Benjamin Code
YouTube 主播和 SaaS 开发者

Estéban Soubiran
Web 开发者和 UnJS 成员
Anthony Bettini
VulnCheck 首席执行官兼创始人

Yaz Jallad
Ninjaparade Digital 创始人
Kevin Olson
Fume.app 创始人
Michael Hoffmann
高级前端开发人员
Harlan Wilton
Nuxt 核心团队成员

Thomas Sanlis
自由开发者和设计师

Benjamin Code
YouTube 主播和 SaaS 开发者

Estéban Soubiran
Web 开发者和 UnJS 成员
Anthony Bettini
VulnCheck 首席执行官兼创始人

Yaz Jallad
Ninjaparade Digital 创始人
Kevin Olson
Fume.app 创始人
Michael Hoffmann
高级前端开发人员
Harlan Wilton
Nuxt 核心团队成员

Thomas Sanlis
自由开发者和设计师

Benjamin Code
YouTube 主播和 SaaS 开发者

Estéban Soubiran
Web 开发者和 UnJS 成员
<script setup lang="ts">
const testimonials = [
{
user: {
name: 'Anthony Bettini',
description: 'CEO and founder of VulnCheck',
avatar: {
src: 'https://media.licdn.com/dms/image/v2/C4E03AQEY3pmXsH8hDg/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1519741249442?e=1746057600&v=beta&t=dvQfBT9ah03MPNy9cnly30ugreeCdxG4nrxV3lwKAC8',
loading: 'lazy'
}
},
quote:
'We were using a SaaS service for the docs site, but were left unfulfilled. We put in the effort to do it in house, with UI Pro and not only did we get complimented by a prospect on our site, but they wanted to know our platform.'
},
{
user: {
name: 'Yaz Jallad',
description: 'Founder Ninjaparade Digital',
avatar: {
src: 'https://pbs.twimg.com/profile_images/1824690890222485504/lQ7v1AGt_400x400.jpg',
loading: 'lazy'
}
},
quote:
"Wow, Nuxt UI Pro is a total game-changer! I'm seriously impressed with the quality, attention to detail, and the insane variety of components you get. It's like hitting the jackpot for any developer. I've saved countless hours that I would've spent stressing over making my apps look good, with amazing accessible UX, and instead, I've been able to focus on the real deal – building the app itself. It's an instant buy for me, every single time. No second thoughts!"
},
{
user: {
name: 'Kevin Olson',
description: 'Founder of Fume.app',
avatar: {
src: 'https://ipx.nuxt.com/f_auto,s_40x40/gh_avatar/acidjazz',
srcset: 'https://ipx.nuxt.com/f_auto,s_80x80/gh_avatar/acidjazz 2x',
loading: 'lazy'
}
},
quote:
'Nuxt UI Pro saves 100s of hours of dev and design time while delivering a clean professional look on any device.'
},
{
user: {
name: 'Michael Hoffmann',
description: 'Senior Frontend Developer',
avatar: {
src: 'https://ipx.nuxt.com/f_auto,s_40x40/gh_avatar/mokkapps',
srcset: 'https://ipx.nuxt.com/f_auto,s_80x80/gh_avatar/mokkapps 2x',
loading: 'lazy'
}
},
quote:
'I decided to replace my custom-built components with a component library and chose Nuxt UI Pro. It only took me a few hours, and the new UI looks more professional. Integrating the library is easy; the components are well-documented and highly customizable. I can only recommend it; this library is my new choice for new SaaS products.'
},
{
user: {
name: 'Harlan Wilton',
description: 'Nuxt core team member',
avatar: {
src: 'https://ipx.nuxt.com/f_auto,s_40x40/gh_avatar/harlan-zw',
srcset: 'https://ipx.nuxt.com/f_auto,s_80x80/gh_avatar/harlan-zw 2x',
loading: 'lazy'
}
},
quote:
'Nuxt UI Pro is my go to component library. Out-of-the-box it handles all of the UI demands I throw at it while looking great. The customisation is really worth thought out, allowing you to override components in a breeze. Always amazed at the improvements dropped in each update as well, the team is doing an amazing job.'
},
{
user: {
name: 'Thomas Sanlis',
description: 'Freelance developer and designer',
avatar: {
src: 'https://pbs.twimg.com/profile_images/1374040164180299791/ACw4G3nZ_400x400.jpg',
loading: 'lazy'
}
},
quote:
"I jumped at the chance to buy the Nuxt team's new UI kit as soon as I saw it. While I'm already a fan of Nuxt UI, the pro version takes it to a whole new level and lets me paste entire blocks into all my projects, saving me a ton of time."
},
{
user: {
name: 'Benjamin Code',
description: 'YouTuber and SaaS builder',
avatar: {
src: 'https://pbs.twimg.com/profile_images/1607353032420769793/I8qQSUfQ_400x400.jpg',
loading: 'lazy'
}
},
quote:
'Nuxt UI has allowed me to develop my SaaS without any prior mockups. The design quality of their components and the intelligence of the DX meant that I was able to try many different layouts for my application until I found the perfect UX for my users. Nuxt UI is the ui-kit I would have dreamed of building myself, and Nuxt UI Pro makes things even easier when you want to go further with your SaaS. Kudos to the team.'
},
{
user: {
name: 'Estéban Soubiran',
description: 'Web developer and UnJS member',
avatar: {
src: 'https://pbs.twimg.com/profile_images/1801649350319218689/aS_X_iTm_400x400.jpg',
loading: 'lazy'
}
},
quote:
"Nuxt UI Pro is my preferred choice for everything, from a POC to a web platform. It's ready to use out-of-the-box and assists me in crafting pixel-perfect UIs. It saves me a significant amount of time while remaining highly customizable. Give it a try, and you won't be let down."
}
]
</script>
<template>
<div class="flex flex-col gap-4 w-full">
<UMarquee
pause-on-hover
:overlay="false"
:ui="{ root: '[--gap:--spacing(4)]', content: 'w-auto py-1' }"
>
<UPageCard
v-for="(testimonial, index) in testimonials"
:key="index"
variant="subtle"
:description="testimonial.quote"
:ui="{
description: 'before:content-[open-quote] after:content-[close-quote] line-clamp-3'
}"
class="w-64 shrink-0"
>
<template #footer>
<UUser v-bind="testimonial.user" size="xl" :ui="{ description: 'line-clamp-1' }" />
</template>
</UPageCard>
</UMarquee>
<UMarquee
pause-on-hover
reverse
:overlay="false"
:ui="{ root: '[--gap:--spacing(4)]', content: 'w-auto py-1' }"
>
<UPageCard
v-for="(testimonial, index) in testimonials"
:key="index"
variant="subtle"
:description="testimonial.quote"
:ui="{
description: 'before:content-[open-quote] after:content-[close-quote] line-clamp-3'
}"
class="w-64 shrink-0"
>
<template #footer>
<UUser v-bind="testimonial.user" size="xl" :ui="{ description: 'line-clamp-1' }" />
</template>
</UPageCard>
</UMarquee>
</div>
</template>
截图
使用 Marquee
组件为您的截图创建无限滚动的动画。
































<template>
<div class="relative w-full h-[400px] bg-muted overflow-hidden">
<UMarquee
reverse
orientation="vertical"
:overlay="false"
:ui="{
root: '[--duration:40s] absolute w-[460px] -left-[100px] -top-[300px] h-[940px] transform-3d rotate-x-55 rotate-y-0 rotate-z-30'
}"
>
<img
v-for="i in 4"
:key="i"
:src="`/blocks/image${i}.png`"
width="460"
height="258"
:alt="`Nuxt UI Screenshot ${i}`"
class="aspect-video border border-default rounded-lg bg-white"
/>
</UMarquee>
<UMarquee
orientation="vertical"
:overlay="false"
:ui="{
root: '[--duration:40s] absolute w-[460px] -top-[400px] left-[480px] h-[1160px] transform-3d rotate-x-55 rotate-y-0 rotate-z-30'
}"
>
<img
v-for="i in [5, 6, 7, 8]"
:key="i"
:src="`/blocks/image${i}.png`"
width="460"
height="258"
:alt="`Nuxt UI Screenshot ${i}`"
class="aspect-video border border-default rounded-lg bg-white"
/>
</UMarquee>
<UMarquee
reverse
orientation="vertical"
:overlay="false"
:ui="{
root: 'hidden md:flex [--duration:40s] absolute w-[460px] -top-[300px] left-[1020px] h-[1060px] transform-3d rotate-x-55 rotate-y-0 rotate-z-30'
}"
>
<img
v-for="i in [9, 10, 11, 12]"
:key="i"
:src="`/blocks/image${i}.png`"
width="460"
height="258"
:alt="`Nuxt UI Screenshot ${i}`"
class="aspect-video border border-default rounded-lg bg-white"
/>
</UMarquee>
</div>
</template>
API
属性
属性 | 默认值 | 类型 |
---|---|---|
as |
|
此组件应渲染为的元素或组件。 |
pauseOnHover |
|
鼠标悬停时暂停跑马灯。 |
reverse |
|
反转跑马灯的方向。 |
orientation |
|
跑马灯的方向。 |
repeat |
|
跑马灯应重复的次数。 |
叠加层 |
|
在跑马灯上显示叠加层。 |
ui |
|
插槽
插槽 | 类型 |
---|---|
default |
|
主题
export default defineAppConfig({
ui: {
marquee: {
slots: {
root: 'group relative flex items-center overflow-hidden gap-(--gap) [--gap:--spacing(16)] [--duration:20s]',
content: 'flex items-center shrink-0 justify-around gap-(--gap) min-w-max'
},
variants: {
orientation: {
horizontal: {
content: 'w-full'
},
vertical: {
content: 'h-full'
}
},
pauseOnHover: {
true: {
content: 'group-hover:[animation-play-state:paused]'
}
},
reverse: {
true: {
content: '![animation-direction:reverse]'
}
},
overlay: {
true: {
root: 'before:absolute before:pointer-events-none before:content-[""] before:z-2 before:from-default before:to-transparent after:absolute after:pointer-events-none after:content-[""] after:z-2 after:from-default after:to-transparent'
}
}
},
compoundVariants: [
{
orientation: 'horizontal',
class: {
root: 'flex-row',
content: 'flex-row animate-[marquee_var(--duration)_linear_infinite] rtl:animate-[marquee-rtl_var(--duration)_linear_infinite] backface-hidden'
}
},
{
orientation: 'horizontal',
overlay: true,
class: {
root: 'before:inset-y-0 before:left-0 before:h-full before:w-1/3 before:bg-gradient-to-r after:inset-y-0 after:right-0 after:h-full after:w-1/3 after:bg-gradient-to-l backface-hidden'
}
},
{
orientation: 'vertical',
class: {
root: 'flex-col',
content: 'flex-col animate-[marquee-vertical_var(--duration)_linear_infinite] rtl:animate-[marquee-vertical-rtl_var(--duration)_linear_infinite] h-[fit-content] backface-hidden'
}
},
{
orientation: 'vertical',
overlay: true,
class: {
root: 'before:inset-x-0 before:top-0 before:w-full before:h-1/3 before:bg-gradient-to-b after:inset-x-0 after:bottom-0 after:w-full after:h-1/3 after:bg-gradient-to-t backface-hidden'
}
}
]
}
}
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
marquee: {
slots: {
root: 'group relative flex items-center overflow-hidden gap-(--gap) [--gap:--spacing(16)] [--duration:20s]',
content: 'flex items-center shrink-0 justify-around gap-(--gap) min-w-max'
},
variants: {
orientation: {
horizontal: {
content: 'w-full'
},
vertical: {
content: 'h-full'
}
},
pauseOnHover: {
true: {
content: 'group-hover:[animation-play-state:paused]'
}
},
reverse: {
true: {
content: '![animation-direction:reverse]'
}
},
overlay: {
true: {
root: 'before:absolute before:pointer-events-none before:content-[""] before:z-2 before:from-default before:to-transparent after:absolute after:pointer-events-none after:content-[""] after:z-2 after:from-default after:to-transparent'
}
}
},
compoundVariants: [
{
orientation: 'horizontal',
class: {
root: 'flex-row',
content: 'flex-row animate-[marquee_var(--duration)_linear_infinite] rtl:animate-[marquee-rtl_var(--duration)_linear_infinite] backface-hidden'
}
},
{
orientation: 'horizontal',
overlay: true,
class: {
root: 'before:inset-y-0 before:left-0 before:h-full before:w-1/3 before:bg-gradient-to-r after:inset-y-0 after:right-0 after:h-full after:w-1/3 after:bg-gradient-to-l backface-hidden'
}
},
{
orientation: 'vertical',
class: {
root: 'flex-col',
content: 'flex-col animate-[marquee-vertical_var(--duration)_linear_infinite] rtl:animate-[marquee-vertical-rtl_var(--duration)_linear_infinite] h-[fit-content] backface-hidden'
}
},
{
orientation: 'vertical',
overlay: true,
class: {
root: 'before:inset-x-0 before:top-0 before:w-full before:h-1/3 before:bg-gradient-to-b after:inset-x-0 after:bottom-0 after:w-full after:h-1/3 after:bg-gradient-to-t backface-hidden'
}
}
]
}
}
})
]
})