过渡

使用 CSS 类控制条件渲染元素的过渡样式,包括嵌套的子级过渡。

要开始,请通过 npm 安装无头 UI

npm install @headlessui/react

要使条件渲染元素过渡,请将其包裹在 Transition 组件中,并使用 show 属性指示它是打开还是关闭。

然后,使用原生 CSS 过渡样式应用动画,通过定位 Transition 组件公开的 data-closed 属性来指定元素的关闭样式。

import { Transition } from '@headlessui/react'
import { useState } from 'react'

function Example() {
  const [open, setOpen] = useState(false)

  return (
    <>
      <button onClick={() => setOpen((open) => !open)}>Toggle</button>
      <Transition show={open}>
        <div className="transition duration-300 ease-in data-[closed]:opacity-0">I will fade in and out</div>
      </Transition>
    </>
  )
}

使用 data-closed 属性定义的样式将用作过渡时的起点,以及过渡时的终点。

对于更复杂的过渡,您还可以使用 data-enterdata-leavedata-transition 属性在过渡的不同阶段应用样式。

使用 data-enterdata-leave 属性在进入和离开时应用不同的过渡样式

import { Transition } from '@headlessui/react'
import clsx from 'clsx'
import { useState } from 'react'

function Example() {
  const [open, setOpen] = useState(false)

  return (
    <div className="relative">
      <button onClick={() => setOpen((open) => !open)}>Toggle</button>
      <Transition show={open}>
        <div
          className={clsx([
            // Base styles
            'absolute w-48 border transition ease-in-out',
            // Shared closed styles
            'data-[closed]:opacity-0',
            // Entering styles
            'data-[enter]:duration-100 data-[enter]:data-[closed]:-translate-x-full',
            // Leaving styles
            'data-[leave]:duration-300 data-[leave]:data-[closed]:translate-x-full',
          ])}
        >
          I will enter from the left and leave to the right
        </div>
      </Transition>
    </div>
  )
}

此示例结合了 data-enterdata-closed 属性来指定进入过渡的起点,并将 data-leavedata-closed 属性结合起来指定离开过渡的终点。

它还使用 data-enterdata-leave 属性指定不同的进入和离开持续时间。

有时您需要使用不同的动画过渡多个元素,但所有这些动画都基于相同的状态。例如,假设用户单击一个按钮打开一个滑过屏幕的侧边栏,并且您还需要同时淡入背景。

您可以通过使用父级 Transition 组件包裹相关元素,并使用 TransitionChild 组件包裹每个需要其自身过渡样式的子元素来实现这一点,TransitionChild 组件将自动与父级 Transition 通信并继承父级的 open 状态。

import { Transition, TransitionChild } from '@headlessui/react'
import { useState } from 'react'

function Example() {
  const [open, setOpen] = useState(false)

  return (
    <>
      <button onClick={() => setOpen(true)}>Open</button>
      {/* The `show` prop controls all nested `TransitionChild` components. */}
<Transition show={open}>
{/* Backdrop */}
<TransitionChild>
<div className="fixed inset-0 bg-black/30 transition duration-300 data-[closed]:opacity-0" onClick={() => setOpen(false)} />
</TransitionChild>
{/* Slide-in sidebar */}
<TransitionChild>
<div className="fixed inset-y-0 left-0 w-64 bg-white transition duration-300 data-[closed]:-translate-x-full"> {/* ... */}
</div>
</TransitionChild>
</Transition> </> ) }

TransitionChild 组件与 Transition 组件具有完全相同的 API,但没有 show 属性,因为 show 值由父级控制。

父级 Transition 组件将始终自动等待所有子级完成过渡,然后再卸载,因此您无需自己管理任何时间安排。

如果您希望元素在首次渲染时过渡,请将 appear 属性设置为 true

如果希望在页面初始加载时或父级条件渲染时某个元素过渡,这将非常有用。

import { Transition } from '@headlessui/react'
import { useState } from 'react'

function Example() {
  const [open, setOpen] = useState(true)

  return (
    <>
      <button onClick={() => setOpen((open) => !open)}>Toggle</button>
<Transition show={open} appear={true}>
<div className="transition duration-300 ease-in data-[closed]:opacity-0">I will fade in on initial render</div> </Transition> </> ) }

属性默认值描述
asFragment
字符串 | 组件

元素或组件过渡应渲染为。

show
布尔值

是否应该显示或隐藏子元素。

appearfalse
布尔值

是否应该在初始挂载时运行过渡。

unmounttrue
布尔值

根据 show 状态是否应该卸载或隐藏元素。

beforeEnter
() => void

在开始进入过渡之前调用的回调。

afterEnter
() => void

在完成进入过渡之后调用的回调。

beforeLeave
() => void

在开始离开过渡之前调用的回调。

afterLeave
() => void

在完成离开过渡之后调用的回调。

属性默认值描述
asFragment
字符串 | 组件

元素或组件过渡子元素应渲染为。

appearfalse
布尔值

是否应该在初始挂载时运行过渡。

unmounttrue
布尔值

根据 show 状态是否应该卸载或隐藏元素。

beforeEnter
() => void

在开始进入过渡之前调用的回调。

afterEnter
() => void

在完成进入过渡之后调用的回调。

beforeLeave
() => void

在开始离开过渡之前调用的回调。

afterLeave
() => void

在完成离开过渡之后调用的回调。

属性描述
data-closed

在过渡之前和过渡时存在。

data-enter

在过渡时存在。

data-leave

在过渡时存在。

data-transition

在过渡时存在。

如果您有兴趣使用无头 UI,请查看 Tailwind UI — 我们精心制作的一套精美设计的组件。

这是支持我们这类开源项目工作的好方法,使我们能够改进它们并保持良好的维护状态。