daisyUI Drawer 组件完全指南:基于 CSS Grid 的响应式侧边栏实现
【免费下载链接】daisyui🌼 🌼 🌼 🌼 🌼 The most popular, free and open-source Tailwind CSS component library项目地址: https://gitcode.com/GitHub_Trending/da/daisyui
本文围绕 daisyUI 官方技能文档 skills/daisyui/components/drawer.md 展开,系统讲解 Drawer(抽屉式侧边栏)的类名体系、标准 HTML 语法、响应式开合机制与纯图标折叠模式,并结合 drawer.css 源码剖析其底层基于 CSS Grid、checkbox状态切换与translate过渡的实现原理。读完本文,你将能够在任意 Tailwind CSS 项目中独立搭建"桌面常驻、移动端抽屉"的导航布局。
Drawer 是什么
在 daisyUI 中,Drawer 是一个基于 CSS Grid 的布局组件,它可以在页面中展示或隐藏一个侧边栏(sidebar),且侧边栏可以放置在页面任意一侧(默认为左侧,使用drawer-end可切换到右侧)。它不依赖任何 JavaScript,而是通过一个隐藏的 checkbox 输入框与 CSS:checked伪类驱动开合状态,这与 daisyUI 其他交互组件(如 Collapse、Dropdown)的设计哲学一致:纯 CSS、零 JS、易于被任何前端框架或原生 HTML 直接使用。
类名体系总览
根据 skills/daisyui/components/drawer.md 的定义,Drawer 由以下五类类名组成:
| 类别 | 类名 | 作用 |
|---|---|---|
| component | drawer | 根容器,建立 Grid 两列布局 |
| part | drawer-toggle | 隐藏的 checkbox 输入框,控制开合状态 |
| part | drawer-content | 页面主体内容区(navbar、正文、footer 都放这里) |
| part | drawer-side | 侧边栏容器,包含菜单与遮罩 |
| part | drawer-overlay | 点击后关闭抽屉的半透明遮罩层 |
| part | drawer-button | 用于触发开合的 label 按钮 |
| placement | drawer-end | 将侧边栏放到页面右侧 |
| modifier | drawer-open | 让侧边栏默认保持打开状态 |
| variant | is-drawer-open:、is-drawer-close: | 针对打开/关闭状态分别应用 Tailwind 工具类 |
其中is-drawer-open:与is-drawer-close:是 daisyUI 提供的状态变体(variant),允许你在侧边栏"展开"与"收起"两种状态下写出完全不同的样式,是实现"收起后只显示图标"这类导航的核心手段,下文会有完整示例。
基础语法结构
Drawer 的标准结构如下:
<div class="drawer {MODIFIER}"> <input id="my-drawer" type="checkbox" class="drawer-toggle" /> <div class="drawer-content">{CONTENT}</div> <div class="drawer-side">{SIDEBAR}</div> </div>四个角色各司其职:
{MODIFIER}是可选的,可以同时包含一个 modifier 类名(如drawer-open)和一个 placement 类名(如drawer-end);drawer-toggle是一个隐藏的 checkbox,必须给它设置一个id(将示例中的my-drawer换成你页面里唯一的 HTML ID);{CONTENT}区域可以放 navbar、站点正文或 footer,它是页面的主体内容;{SIDEBAR}区域通常放一个菜单(menu),例如:
<ul class="menu p-4 w-80 min-h-full bg-base-100 text-base-content"> <li><a>Item 1</a></li> <li><a>Item 2</a></li> </ul>{MODIFIER}可选,可包含一个 modifier 类名和一个 placement 类名。下面这种写法同时应用了 placement(右侧)与打开状态:
<div class="drawer drawer-end drawer-open"> <input id="my-drawer" type="checkbox" class="drawer-toggle" /> <div class="drawer-content">{CONTENT}</div> <div class="drawer-side">{SIDEBAR}</div> </div>如何打开与关闭 Drawer
由于drawer-toggle是一个隐藏 checkbox,打开/关闭抽屉的本质就是切换这个 checkbox 的勾选状态。daisyUI 推荐的方式是使用一个for属性与 checkbox 的id匹配的<label>:
<label for="my-drawer" class="btn drawer-button">Open/close drawer</label>这里的my-drawer必须与drawer-toggle输入框的id完全一致。点击 label 时浏览器会自动切换 checkbox 的勾选状态,从而触发 Drawer 的开合。drawer-button类负责让该 label 与状态联动(例如在 checkbox 获得焦点时显示焦点轮廓)。
除了按钮,侧边栏内配套的半透明遮罩drawer-overlay也承担关闭功能——点击遮罩区域即可关闭抽屉:
<label for="my-drawer" aria-label="close sidebar" class="drawer-overlay"></label>从源码 drawer.css 可以看到,.drawer-overlay拥有cursor-pointer与place-self-stretch属性,并带有一个半透明底色oklch(0% 0 0 / 40%),它铺满整个侧边栏区域,点击即触发 checkbox 取消勾选,实现"点击遮罩关闭"的交互。
底层原理:从源码看 Drawer 如何工作
Grid 双列布局
.drawer根元素在 drawer.css 中被定义为:
.drawer { @apply relative grid; width: 100%; grid-auto-columns: max-content auto; }它使用grid-auto-columns: max-content auto建立两列布局:第一列(max-content)留给侧边栏,第二列(auto)留给内容区。.drawer-content通过col-start-2 row-start-1 min-w-0固定在第二列,且min-w-0保证内容区不会因内部长内容而撑破 Grid 轨道。
checkbox 驱动状态
.drawer-toggle的样式为:
.drawer-toggle { @apply fixed h-0 w-0 appearance-none opacity-0; }它是一个尺寸为 0、完全透明的隐藏 checkbox。当它被勾选(:checked)时,其后的兄弟元素.drawer-side会切换到可见状态:
:where(&:checked ~ .drawer-side) { @apply pointer-events-auto visible overflow-y-auto opacity-100; }与此同时,侧边栏内部的非遮罩内容(即菜单本体)通过translate从屏幕外滑入:
> :not(.drawer-overlay) { transform: none; /* 或 translate: 0% */ will-change: auto; }默认(未勾选)状态下,.drawer-side被设置为pointer-events-none invisible fixed start-0 top-0 z-10,配合opacity-0隐藏;其内部非遮罩内容默认translate: -100%(RTL 下为translate: 100%),即完全位于视口之外,并通过transition对translate和width做平滑过渡。这就是抽屉滑入滑出动画的实现机制——纯 CSS transform,性能良好且不依赖 JS。
页面滚动锁
抽屉打开时,daisyUI 还会锁定页面背景的滚动。勾选状态通过:root:has(&:checked)将根元素上的--page-scroll-lock自定义属性置空,进而触发 rootscrolllock.css 中的overflow: hidden,同时由 rootscrollgutter.css 配合scrollbar-gutter: stable保留滚动条占位,避免页面出现跳动。这一系列机制都由 daisyUI 的 base 样式自动完成,使用 Drawer 时无需手动编写任何滚动锁代码。
实战示例一:桌面常驻、移动端抽屉
这是 Drawer 最经典的用法:在lg及以上屏幕侧边栏始终可见,在小屏幕上则收起为抽屉、通过按钮开合。
<div class="drawer lg:drawer-open"> <input id="my-drawer-3" type="checkbox" class="drawer-toggle" /> <div class="drawer-content flex flex-col items-center justify-center"> <!-- Page content here --> <label for="my-drawer-3" class="btn drawer-button lg:hidden"> Open drawer </label> </div> <div class="drawer-side"> <label for="my-drawer-3" aria-label="close sidebar" class="drawer-overlay"></label> <ul class="menu bg-base-200 min-h-full w-80 p-4"> <!-- Sidebar content here --> <li><button>Sidebar Item 1</button></li> <li><button>Sidebar Item 2</button></li> </ul> </div> </div>关键点在于lg:drawer-open:这是 Tailwind 的响应式变体与 daisyUI 的drawer-openmodifier 的组合。从 drawer.css 看,.drawer-open会把侧边栏改为sticky定位并保持visible、w-auto、opacity-100,同时隐藏 checkbox(display: none),遮罩层变为cursor-default且背景透明,侧边栏内容translate: 0%常驻页面。因此在lg断点以上它是一块固定的侧栏;在lg以下,drawer-open不生效,侧边栏回归抽屉形态,由内容区的lg:hidden按钮控制开合。
注意此时drawer-side内部的遮罩 label 依然保留——在移动端抽屉形态下它负责"点击空白关闭",而在桌面常驻形态下它自动变为透明且不可交互,两者互不冲突。
实战示例二:收起态只显示图标的可折叠侧边栏
第二个官方示例展示了如何利用is-drawer-open:与is-drawer-close:变体,让侧边栏在"收起"时只显示图标、在"展开"时显示图标加文字,并配合 daisyUI 的 tooltip 在收起态下悬停显示名称:
<div class="drawer lg:drawer-open"> <input id="my-drawer-4" type="checkbox" class="drawer-toggle" /> <div class="drawer-content"> <!-- Page content here --> </div> <div class="drawer-side is-drawer-close:overflow-visible"> <label for="my-drawer-4" aria-label="close sidebar" class="drawer-overlay"></label> <div class="is-drawer-close:w-14 is-drawer-open:w-64 bg-base-200 flex flex-col items-start min-h-full"> <!-- Sidebar content here --> <ul class="menu w-full grow"> <!-- list item --> <li> <button class="is-drawer-close:tooltip is-drawer-close:tooltip-right" contenteditable="false">【免费下载链接】daisyui🌼 🌼 🌼 🌼 🌼 The most popular, free and open-source Tailwind CSS component library
项目地址: https://gitcode.com/GitHub_Trending/da/daisyui创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考