111k

Carousel

一个基于 Embla 构建、支持动效和滑动的轮播组件。

1
2
3
4
5
import * as React from "react"
import { Card, CardContent } from "@/components/ui/card"
import {

关于

Carousel 组件基于 Embla Carousel 库构建。

安装

pnpm dlx shadcn@latest add carousel

用法

import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/ui/carousel"
<Carousel>
  <CarouselContent>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

示例

尺寸

要设置项目尺寸,可以在 <CarouselItem /> 上使用 basis 工具类。

1
2
3
4
5
import * as React from "react"
import { Card, CardContent } from "@/components/ui/card"
import {
// 轮播宽度的 33%。
<Carousel>
  <CarouselContent>
    <CarouselItem className="basis-1/3">...</CarouselItem>
    <CarouselItem className="basis-1/3">...</CarouselItem>
    <CarouselItem className="basis-1/3">...</CarouselItem>
  </CarouselContent>
</Carousel>
// 小屏幕上占 50%,大屏幕上占 33%。
<Carousel>
  <CarouselContent>
    <CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
    <CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
    <CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
  </CarouselContent>
</Carousel>

间距

要设置项目之间的间距,可以在 <CarouselItem /> 上使用 pl-[VALUE] 工具类,并在 <CarouselContent /> 上使用负值 -ml-[VALUE]

1
2
3
4
5
import * as React from "react"
import { Card, CardContent } from "@/components/ui/card"
import {
<Carousel>
  <CarouselContent className="-ml-4">
    <CarouselItem className="pl-4">...</CarouselItem>
    <CarouselItem className="pl-4">...</CarouselItem>
    <CarouselItem className="pl-4">...</CarouselItem>
  </CarouselContent>
</Carousel>
<Carousel>
  <CarouselContent className="-ml-2 md:-ml-4">
    <CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
    <CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
    <CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
  </CarouselContent>
</Carousel>

方向

使用 orientation 属性可以设置轮播方向。

1
2
3
4
5
import * as React from "react"
import { Card, CardContent } from "@/components/ui/card"
import {
<Carousel orientation="vertical | horizontal">
  <CarouselContent>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
  </CarouselContent>
</Carousel>

选项

你可以使用 opts 属性向轮播传入选项。更多信息请参见 Embla Carousel 文档

<Carousel
  opts={{
    align: "start",
    loop: true,
  }}
>
  <CarouselContent>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
  </CarouselContent>
</Carousel>

API

使用状态和 setApi 属性可以获取 carousel API 实例。

1
2
3
4
5
Slide 0 of 0
"use client"

import * as React from "react"
import { type CarouselApi } from "@/components/ui/carousel"
 
export function Example() {
  const [api, setApi] = React.useState<CarouselApi>()
  const [current, setCurrent] = React.useState(0)
  const [count, setCount] = React.useState(0)
 
  React.useEffect(() => {
    if (!api) {
      return
    }
 
    setCount(api.scrollSnapList().length)
    setCurrent(api.selectedScrollSnap() + 1)
 
    api.on("select", () => {
      setCurrent(api.selectedScrollSnap() + 1)
    })
  }, [api])
 
  return (
    <Carousel setApi={setApi}>
      <CarouselContent>
        <CarouselItem>...</CarouselItem>
        <CarouselItem>...</CarouselItem>
        <CarouselItem>...</CarouselItem>
      </CarouselContent>
    </Carousel>
  )
}

事件

你可以使用 setApi 返回的 api 实例监听事件。

import { type CarouselApi } from "@/components/ui/carousel"
 
export function Example() {
  const [api, setApi] = React.useState<CarouselApi>()
 
  React.useEffect(() => {
    if (!api) {
      return
    }
 
    api.on("select", () => {
      // 在选择时执行操作。
    })
  }, [api])
 
  return (
    <Carousel setApi={setApi}>
      <CarouselContent>
        <CarouselItem>...</CarouselItem>
        <CarouselItem>...</CarouselItem>
        <CarouselItem>...</CarouselItem>
      </CarouselContent>
    </Carousel>
  )
}

更多关于事件的用法,请参见 Embla Carousel 文档

插件

你可以使用 plugins 属性为轮播添加插件。

import Autoplay from "embla-carousel-autoplay"
 
export function Example() {
  return (
    <Carousel
      plugins={[
        Autoplay({
          delay: 2000,
        }),
      ]}
    >
      // ...
    </Carousel>
  )
}
1
2
3
4
5
"use client"

import * as React from "react"

RTL

要在 shadcn/ui 中启用 RTL 支持,请参见 RTL 配置指南

١
٢
٣
٤
٥
"use client"

import * as React from "react"

在为 RTL 语言本地化轮播时,你需要在 opts 属性中设置 direction 选项,使其与文本方向一致。这样可以确保轮播按正确方向滚动。

<Carousel
  dir={dir}
  opts={{
    direction: dir,
  }}
>
  <CarouselContent>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
  </CarouselContent>
  <CarouselPrevious className="rtl:rotate-180" />
  <CarouselNext className="rtl:rotate-180" />
</Carousel>

direction 选项接受 "ltr""rtl",并应与 dir 属性值一致。你也可以使用 rtl:rotate-180 类旋转导航按钮,以确保它们指向正确方向。

API 参考

有关属性和插件的更多信息,请参见 Embla Carousel 文档