在传统前端开发中,如果想要实现一个折叠面板效果,我们需要使用 JavaScript 来监听点击事件并改变元素高度。而在 Tailwind CSS 中,我们则提倡 “能用 CSS 解决的就不用 JavaScript”。
Tailwind CSS 折叠面板原理
在 Tailwind CSS 中,如果想要实现折叠面板,主要有以下 2 种思路:
1. 原生标签法(极简)
使用 HTML5 自带的 details 和 summary 标签。这种方式的好处是浏览器原生支持,语义化更好,并且完全不需要任何逻辑代码。
2. 复选框状态法(高级)
使用一个隐藏的 <input type="checkbox"> 配合 Tailwind 的 peer 修饰符,然后通过监听复选框的 checked 状态,来动态改变下方内容区域的高度和显示状态。
Tailwind CSS 折叠面板示例
接下来,我们通过几个简单的例子来讲解一下如何使用 Tailwind CSS 来实现折叠面板效果。
示例 1:FAQ 折叠
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<script src="https://unpkg.com/@tailwindcss/browser@4"></script>
</head>
<body class="p-10 bg-green-50">
<div class="w-full max-w-md space-y-4">
<h2 class="mb-6 text-2xl font-black text-emerald-900 text-center">常见问题</h2>
<details class="group bg-white rounded-2xl border border-emerald-100 shadow-sm overflow-hidden">
<summary class="flex items-center justify-between p-5 font-bold text-emerald-900 cursor-pointer list-none">
<span>绿叶网的教程,适合 0 基础小白学习吗?</span>
<svg class="w-5 h-5 text-emerald-500 transition-transform duration-300 group-open:rotate-180" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"></path>
</svg>
</summary>
<div class="px-5 pb-5 text-emerald-800/70 text-sm leading-relaxed border-t border-emerald-50 pt-4">
那必须的。绿叶网专注于教程的易懂性,让完全 0 基础的小白也能更快上手。
</div>
</details>
</div>
</body>
</html>默认情况下,页面效果如下图 1 所示。当点击选项时,页面效果如下图 2 所示。


分析:
在这个例子中,我们利用了 Tailwind CSS v4 的一个小技巧:group-open。
当 details 标签展开时,它会自动带上一个 open 属性。Tailwind CSS 能够捕捉到这个状态。
我们通过给父级设置 group,然后在箭头图标上写 group-open:rotate-180,就实现了点击时箭头自动旋转的平滑动效,完全不需要编写一行 JavaScript。
示例 2:peer 状态切换(纯 CSS 交互)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<script src="https://unpkg.com/@tailwindcss/browser@4"></script>
</head>
<body class="p-10 bg-emerald-800">
<div class="w-full max-w-md bg-white/10 backdrop-blur-md rounded-3xl p-2 border border-white/20">
<label class="relative block cursor-pointer">
<input type="checkbox" class="peer hidden">
<div class="flex items-center justify-between p-4 text-white font-bold bg-white/5 rounded-2xl hover:bg-white/10 transition-all">
<span>Vue 快速上手</span>
<span class="text-2xl transition-transform duration-300 peer-checked:rotate-45">+</span>
</div>
<div class="max-h-0 overflow-hidden transition-all duration-500 ease-in-out peer-checked:max-h-40">
<div class="p-4 text-white/70 text-sm">
从最基础的 Vue 语法入手,每一个知识点都 “掰开揉碎”。用通俗易懂的方式来讲解,让 0 基础小白能够快速上手。知识点全面、系统、有深度,让老手也能收获满满!
</div>
</div>
</label>
</div>
</body>
</html>

分析:
在这个例子中,首先我们通过 “peer” 类名标记了隐藏的 input 标签。接下来重点在于 “peer-checked:max-h-40”。
当复选框被勾选时(即用户点击了 label 区域),它会触发下方兄弟元素的样式变化。这种方式的灵活性非常高,我们可以用它来控制任何复杂的交互组合。
常见问题
1. 为什么我的折叠面板展开时没有平滑动画?
如果你使用的是 display: none 和 display: block 的切换,浏览器是无法计算中间过渡状态的。为了实现丝滑的展开效果,我们通常会使用 max-h-0 到 max-h-{size} 的高度过渡,或者改变 grid-template-rows 的比例。
2. 多个折叠面板如何实现 “互斥”(开一个关另一个)呢?
对于原生方案,我们只需要给多个 details 标签设置相同的 name 属性(如 name="faq"),浏览器就会自动帮你实现这种 “手风琴” 互斥效果。
