如何在NextJS+Tailwind CSS中实现酒店设施展开收起功能
问题
我正在开发一个展示酒店设施的页面,希望实现一个可隐藏的设施区块:点击「Show more amenities」按钮可展开该区块,点击「Show less amenities」按钮可将其收起。请问如何在NextJS框架中配合Tailwind CSS完成此交互功能?
示例1(收起状态):
示例2(展开状态的设施区块):
现有代码片段:
'use client' import Image from 'next/image' import { useState, useEffect } from "react"; export default function Lodge() { return ( <div className="w-full h-[8964px] bg-white shadow-sm"> <div className="grid grid-cols-2 gap-4"> ... <div className="text-[28px] font-medium leading-normal text-[#313131] underline flex flex-row gap-5 py-16 cursor-pointer"> Show more amenties <Image src="/images/icon down.svg" alt="icon-down" width={26} height={26} /> </div> <div className="grid grid-cols-2 gap-4"> <div className=""> <div className="text-[32px] font-bold leading-normal text-[#313131]"> Heating & Cooling <div className="text-[24px] font-medium leading-normal text-[#313131] flex flex-row items-end gap-5"> <Image src="/images/lodge/fan icon.svg" alt="fan-icon" width={40} height={40} /> Portable fans </div> </div> <div className="text-[32px] font-bold leading-normal text-[#313131]"> Internet & Working <div className="text-[24px] font-medium leading-normal text-[#313131] flex flex-row items-end gap-5"> <Image src="/images/lodge/wifi icon.svg" alt="wifi-icon" width={40} height={40} /> WI-FI </div> <div className="text-[24px] font-medium leading-normal text-[#313131] flex flex-row items-end gap-5"> <Image src="/images/lodge/desk icon.svg" alt="desk-icon" width={40} height={40} /> Working zone </div> </div> ... etc
解决方案
1. 用useState管理展开状态
在组件内部添加状态变量控制设施区块的显示/隐藏,初始设为false(默认收起)。
2. 修改按钮交互逻辑
- 根据状态切换按钮文本:展开时显示「Show less amenities」,收起时显示「Show more amenities」
- 给按钮绑定点击事件,切换状态值
- 图标可通过Tailwind的旋转类实现方向切换,无需额外图标资源
3. 用Tailwind控制区块显示与动画
给设施区块添加条件类,实现平滑的展开/收起过渡:
- 收起状态:
max-h-0 overflow-hidden opacity-0 - 展开状态:
max-h-[2000px] opacity-100 - 配合
transition-all duration-300实现动画效果
完整修改代码
'use client' import Image from 'next/image' import { useState } from "react"; export default function Lodge() { // 管理设施区块展开状态,默认收起 const [isAmenitiesExpanded, setIsAmenitiesExpanded] = useState(false); // 切换展开/收起状态 const toggleAmenities = () => { setIsAmenitiesExpanded(!isAmenitiesExpanded); }; return ( <div className="w-full h-[8964px] bg-white shadow-sm"> <div className="grid grid-cols-2 gap-4"> {/* 其他页面内容 */} ... {/* 切换按钮 */} <div onClick={toggleAmenities} className="text-[28px] font-medium leading-normal text-[#313131] underline flex flex-row items-center gap-5 py-16 cursor-pointer" > {isAmenitiesExpanded ? 'Show less amenities' : 'Show more amenities'} <Image src="/images/icon down.svg" alt={isAmenitiesExpanded ? "icon-up" : "icon-down"} width={26} height={26} className={`transition-transform ${isAmenitiesExpanded ? 'rotate-180' : ''}`} /> </div> {/* 设施区块:带过渡动画的显示/隐藏 */} <div className={`grid grid-cols-2 gap-4 transition-all duration-300 ease-in-out ${isAmenitiesExpanded ? 'opacity-100 max-h-[2000px]' : 'opacity-0 max-h-0 overflow-hidden'}`}> <div className=""> <div className="text-[32px] font-bold leading-normal text-[#313131]"> Heating & Cooling <div className="text-[24px] font-medium leading-normal text-[#313131] flex flex-row items-end gap-5"> <Image src="/images/lodge/fan icon.svg" alt="fan-icon" width={40} height={40} /> Portable fans </div> </div> <div className="text-[32px] font-bold leading-normal text-[#313131]"> Internet & Working <div className="text-[24px] font-medium leading-normal text-[#313131] flex flex-row items-end gap-5"> <Image src="/images/lodge/wifi icon.svg" alt="wifi-icon" width={40} height={40} /> WI-FI </div> <div className="text-[24px] font-medium leading-normal text-[#313131] flex flex-row items-end gap-5"> <Image src="/images/lodge/desk icon.svg" alt="desk-icon" width={40} height={40} /> Working zone </div> </div> {/* 其他设施内容 */} ... etc </div> </div> </div> </div> ); }
关键说明
- 依托Next.js客户端组件的
useState实现状态管理,符合框架规范 - 使用
max-h而非hidden实现动画,避免元素直接消失的生硬感 - 图标旋转通过
rotate-180类实现,减少资源文件依赖
内容的提问来源于stack exchange,提问作者userunknown
相关产品推荐
相关产品推荐

