reactjs 我如何动画的高度下拉菜单使用顺风css

laik7k3q  于 2023-04-11  发布在  React
关注(0)|答案(1)|浏览(139)

我正在使用:Tailwindcss,React和Next.js作为副项目。
我试图创建一个响应导航栏,显示汉堡菜单时,屏幕大小达到顺风定义的“sm”大小。
当我单击汉堡图标时,我希望菜单从高度0过渡到max-h-40。
我觉得我在下面的代码中遗漏了一些琐碎的东西,希望另一个人看到这一点可以看到我遗漏了什么?

navbar.tsx

"use client";

import Image from "next/image";
import Link from "next/link";
import {
  useState
} from "react";
import logo from "../public/finallang_favicon.ico";

export default function Navbar() {
  const [showMenu, setShowMenu] = useState(false);
  const toggleMenu = () => {
    setShowMenu(!showMenu);
  };
  return ( <
    div >
    <
    nav className = "flex items-center justify-between flex-grow w-auto py-3 text-center border-b px-9 sm:w-auto" >
    <
    div className = "flex items-center justify-center flex-shrink-0 sm:mr-6" >
    <
    Link href = "/" >
    <
    Image src = {
      logo
    }
    alt = "Logo"
    width = {
      48
    }
    height = {
      48
    }
    /> <
    /Link> <
    /div> <
    div className = "hidden text-sm sm:block" >
    <
    Link href = "#"
    className = "block mt-4 sm:mr-4 text-slate-900 hover:text-slate-700 sm:mt-0 sm:inline-block" >
    About <
    /Link> <
    Link href = "#"
    className = "block mt-4 sm:mr-4 text-slate-900 hover:text-slate-700 sm:mt-0 sm:inline-block" >
    Blog <
    /Link> <
    Link href = "#"
    className = "block mt-4 text-slate-900 hover:text-slate-700 sm:mt-0 sm:inline-block" >
    Contact Me <
    /Link> <
    /div> <
    div >
    <
    button className = "hidden px-4 py-2 text-sm leading-none rounded text-slate-100 hover:text-white sm:inline-block bg-brand" >
    Download <
    /button> <
    button onClick = {
      toggleMenu
    }
    aria - label = "Toggle navigation menu"
    className = "text-gray-400 align-middle sm:hidden hover:text-gray-900 focus:ring-2 rounded-md" >
    <
    svg xmlns = "http://www.w3.org/2000/svg"
    fill = "none"
    viewBox = "0 0 24 24"
    strokeWidth = {
      2
    }
    stroke = "currentColor"
    className = "w-6 h-6" >
    <
    path strokeLinecap = "round"
    strokeLinejoin = "round"
    d = "M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" / >
    <
    /svg> <
    /button> <
    /div> <
    /nav> {
      showMenu &&
        <
        div className = {
          `${showMenu ? "max-h-40" : "h-0"} text-sm text-center sm:hidden transition-all duration-500 ease-in-out overflow-hidden`
        } >
        <
        Link href = "/about"
      className = "block mt-4 text-slate-900 hover:text-slate-700" >
        About <
        /Link> <
        Link href = "/blog"
      className = "block mt-4 text-slate-900 hover:text-slate-700" >
        Blog <
        /Link> <
        Link href = "/contact"
      className = "block mt-4 text-slate-900 hover:text-slate-700" >
        Contact Me <
        /Link> <
        /div>
    } <
    /div>
  );
}

我尝试过的事情

  • height: "height"作为transitionProperty添加到tailwind.config.js
  • 添加一个可能丢失的overflow-hidden类名到我的menus类
  • 在下拉菜单的类中在transition-alltransition-[height]之间切换
    当前行为Gif of current behavior
    我希望发生的事情
  • 下拉菜单应在500 ms的持续时间内从高度0过渡到最大高度10 rems(max-h-40),并使用易进易出过渡计时功能。
idfiyjo8

idfiyjo81#

问题说明

DOM挂载

通过代码段的条件渲染:

{showMenu &&
  <div className="…">

意味着元素被装入DOM或从DOM中取出。转换不会在元素被装入/卸载的同一帧上播放。

CSS属性转换

此外,您正在使用菜单容器的条件类更改不同的CSS属性:

${showMenu ? "max-h-40" : "h-0"}

max-h-40对应于max-height: 10rem,而h-0对应于height: 0。这意味着我们在这里从它们的初始值max-heightheight改变两个值。根据MDN,max-height的初始值为noneheight的初始值为auto。这些值相对于showMenu的变化如下:
| showMenu|true|false|
| --------------|--------------|--------------|
| max-height|10rem|none|
| height|auto|0|
但是,height: 0height: auto之间不会发生过渡,而max-height: nonemax-height: 10rem将创建从全高到10rem高度的过渡,这似乎也不是你想要的!

解决方案

  • 我们需要保持菜单容器在任何时候都挂载到DOM上。没有条件挂载。
  • max-height: 0max-height: 10rem之间的过渡
  • 使用visibility: hidden隐藏元素,这样就不能通过tab键聚焦到隐藏的子元素中。
return (
  <div>
    …
    <div className={`${showMenu ? "max-h-40" : "max-h-0 invisible"} text-sm text-center sm:hidden transition-all duration-500 ease-in-out overflow-hidden`}>
      …
    </div>
  </div>
);

相关问题