daisyUI Stack 组件完全指南:用 CSS Grid 让元素层层堆叠
Stack 是 daisyUI 中一个精巧的布局组件:它通过单个 stack 类,把多个子元素(图片、卡片、通知等)在同一个平面位置上叠放起来,形成“卡牌叠层”或“多图层”的视觉效果。本文以 Stack 官方文档/components/stack/+page.md>)为主体,结合 stack.css 源码与仓库内技能文档,讲解其类名体系、方向修饰符与对齐原理,并给出可直接复制的 6 类实战示例。读完你可以熟练地用 stack、stack-top、stack-start 等类名搭建层叠图册、堆叠卡片与通知列表。
组件定位:一个类,实现多元素层叠
Stack 组件的核心作用是“把一个元素放到另一个元素上面”(Puts the children elements on top of each other)。与 absolute 定位手动堆叠不同,Stack 完全基于 CSS Grid 隐式网格实现,无需任何 JS 与绝对定位坐标,容器的直接子元素会自动整齐地偏移错开,呈现微妙的立体叠层感。
依据组件页面的 frontmatter 元数据,Stack 提供以下类名:
| 类型 | 类名 | 作用 | 是否为默认 |
|---|---|---|---|
| component | stack |
让子元素彼此叠放 | 是 |
| modifier | stack-bottom |
将子元素向底部对齐 | 是(默认方向) |
| modifier | stack-top |
将子元素向顶部对齐 | 否 |
| modifier | stack-start |
将子元素向起始侧(水平方向)对齐 | 否 |
| modifier | stack-end |
将子元素向末尾侧(水平方向)对齐 | 否 |
提示:修饰符以
stack前缀与组件类连接使用,例如stack stack-top。frontmatter 中标注stack-bottom为default: true,也就是说不写任何修饰符时,默认行为即等价于底部对齐的堆叠,这与源码中.stack与.stack-bottom共用同一组栅格规则完全一致。
叠放原理:从源码看 5 列 5 行栅格
要理解 Stack 为什么能产生“每张牌边缘可见”的效果,关键在于阅读组件真正的样式实现 stack.css:
.stack {
@layer daisyui.l1.l2.l3 {
@apply inline-grid;
grid-template-columns: 3px 4px 1fr 4px 3px;
grid-template-rows: 3px 4px 1fr 4px 3px;
}
}
容器被声明为 inline-grid,并划分成 5 列 × 5 行的轨道网格,轨道宽度为 3px 4px 1fr 4px 3px——即两侧留出 3px/4px 的偏移余量,中间 1fr 是真正的内容区域。子元素则通过 grid-column / grid-row 落到不同的轨道组合上,从而让每一层都相对上一层产生固定偏移。
在此基础上,CSS 还利用级联选择器对子元素做了统一的尺寸与层叠处理:
& > * {
@apply h-full w-full;
}
所有直接子元素被强制铺满父级尺寸,这正是文档中“可以用 w-*、h-* 设置容器宽高从而使所有子项同尺寸”这一规则的底层保障。容器尺寸由外部 Tailwind 工具类决定,内部每个 > * 自动撑满,因此它们天然等大。
关于层叠顺序,源码按 DOM 顺序分配了递增的可见权重:
- 第 1 个子元素(
:nth-child(1))得到z-3; - 第 2 个子元素(
:nth-child(2))得到z-2与opacity-90; - 第 3 个及以后的子元素(
:nth-child(n + 2))得到opacity-70。
也就是说:排在最前面的 HTML 子元素显示在最上层(层级最高),后续子元素逐层下沉并略微变透明。第 3 层开始统一 70% 透明度、第 2 层 90% 透明度,因此下面的“牌”隐约透出,产生真实的厚度观感。要调整透明度,直接在对应子元素上追加 Tailwind 的 opacity-* 工具类覆盖即可。
四种对齐修饰符的栅格差异
stack-top、stack-bottom、stack-start、stack-end 本质上是四套不同的栅格坐标方案,源码把它们放在 @layer daisyui.l1.l2 中,逐一改写子元素的 grid-column / grid-row:
stack-bottom(默认):中间层落在grid-column: 3 / 4、grid-row: 3 / 6,让整叠元素沉向容器底部,第 1 层跨1 / 6与1 / 4;stack-top:中间层对应grid-row: 1 / 4,整叠元素从容器顶部开始向上层展开;stack-start:中间层对应grid-column: 1 / 4、grid-row: 3 / 4,把“牌边”偏移引导到水平起始侧;stack-end:中间层对应grid-column: 3 / 6、grid-row: 3 / 4,把“牌边”偏移引导到水平末尾侧。
可以简单记忆为:竖向修饰符(top/bottom)控制“牌堆露出的边在垂直方向的哪一端”,横向修饰符(start/end)控制“露出的边在水平方向的哪一侧”。
基础用法:三等分块与等尺寸规则
Stack 最基础的形态是三个色块叠放。以下代码移除了文档站点的类前缀占位符,可直接粘贴运行:
<div class="stack h-20 w-32">
<div class="grid rounded-box bg-primary text-primary-content place-content-center">1</div>
<div class="grid rounded-box bg-accent text-accent-content place-content-center">2</div>
<div class="grid rounded-box bg-secondary text-secondary-content place-content-center">3</div>
</div>
这里有两个关键细节:
- 容器必须有确定尺寸。
h-20 w-32(或size-28这类工具类)定义了整个 Stack 的宽高,由& > * { height: 100%; width: 100% }传播给所有子元素,保证它们完全等大; - 子元素负责自己的视觉样式。示例使用
bg-primary、bg-accent、bg-secondary等 daisyUI 语义色,以及 Tailwind 的grid place-content-center让数字居中。
由于容器是 inline-grid,若不在外层使用 w-*/h-*,也可用页面布局类控制尺寸——但务必记住:stack 组件本身不负责尺寸,尺寸一律交给 Tailwind 工具类。这一点在技能文档 stack.md 的 Rules 中同样被强调:“Use the w-* and h-* classes to set the stack width and height. These classes make all the items the same size.”
实战一:层叠图片画廊
把三张相同宽高的图片叠放,能立刻营造出“一叠照片”的浏览感,适合做相册入口或轮播样式。只需给每张图片追加 rounded-box 圆角,让叠层边缘更精致:
<div class="stack w-48">
<img alt="示例图片 1" src="your-image-1.webp" class="rounded-box" />
<img alt="示例图片 2" src="your-image-2.webp" class="rounded-box" />
<img alt="示例图片 3" src="your-image-3.webp" class="rounded-box" />
</div>
第 1 张图片默认浮在最上层(z-3),第 2、3 张按 90%/70% 透明度下沉,露出的左侧与底部边缘形成整齐的错位,无需任何定位代码。使用图片时请将 src 替换为实际部署的图片路径。
实战二:卡片与通知堆叠
Stack 与 daisyUI 的 card 组件组合非常自然。给每张卡片设置不同强度的阴影(shadow-md、shadow、shadow-sm),叠层之间就能区分层次并浮现真实的“压着”关系:
<div class="stack">
<div class="text-center shadow-md card bg-base-200">
<div class="card-body">A</div>
</div>
<div class="text-center shadow card bg-base-200">
<div class="card-body">B</div>
</div>
<div class="text-center shadow-sm card bg-base-200">
<div class="card-body">C</div>
</div>
</div>
更贴近真实产品的场景是“通知抽屉”风格:同一卡片反复堆叠 3 次,只在标题与正文上区分文案,模拟出多条未读消息层叠的视觉(示例中的 card-title、card-body 完整结构):
<div class="stack">
<div class="shadow-md bg-base-100 card">
<div class="card-body">
<h2 class="card-title">Notification 1</h2>
<p>You have 3 unread messages. Tap here to see.</p>
</div>
</div>
<div class="shadow-md bg-base-100 card">
<div class="card-body">
<h2 class="card-title">Notification 2</h2>
<p>You have 3 unread messages. Tap here to see.</p>
</div>
</div>
<div class="shadow-md bg-base-100 card">
<div class="card-body">
<h2 class="card-title">Notification 3</h2>
<p>You have 3 unread messages. Tap here to see.</p>
</div>
</div>
</div>
此时使用 bg-base-100、border border-base-content 这类语义色,可保证通知卡片在浅色/深色主题下都能正确显示。
实战三:用修饰符调整露出方向
叠层露出的“牌边”方向可通过修饰符自由切换。下面三组代码分别对应顶部对齐、起始侧对齐、末尾侧对齐的卡片叠层,其余结构与基础卡片堆叠完全一致:
<!-- 子元素向顶部对齐:stack-top -->
<div class="stack stack-top size-28">
<div class="text-center border border-base-content card bg-base-100">
<div class="card-body">A</div>
</div>
<div class="text-center border border-base-content card bg-base-100">
<div class="card-body">B</div>
</div>
<div class="text-center border border-base-content card bg-base-100">
<div class="card-body">C</div>
</div>
</div>
<!-- 子元素向水平起始侧对齐:stack-start -->
<div class="stack stack-start size-28">
<div class="text-center border border-base-content card bg-base-100">
<div class="card-body">A</div>
</div>
<div class="text-center border border-base-content card bg-base-100">
<div class="card-body">B</div>
</div>
<div class="text-center border border-base-content card bg-base-100">
<div class="card-body">C</div>
</div>
</div>
<!-- 子元素向水平末尾侧对齐:stack-end -->
<div class="stack stack-end size-28">
<div class="text-center border border-base-content card bg-base-100">
<div class="card-body">A</div>
</div>
<div class="text-center border border-base-content card bg-base-100">
<div class="card-body">B</div>
</div>
<div class="text-center border border-base-content card bg-base-100">
<div class="card-body">C</div>
</div>
</div>
三者的共同点是都通过 size-28 统一了容器边长;差别仅在于 stack-top / stack-start / stack-end 修饰符驱动了源码中三套不同的 grid-row / grid-column 映射,因此每一叠卡片的“错位边缘”出现在不同方向。默认的 stack-bottom 则无需书写(与 stack 单独使用等价)。
文档站点的 $$ 占位符说明
在 Stack 官方页面/components/stack/+page.md>) 的代码块中,你会看到 $$stack、$$card 这样的写法。$$ 并非 daisyUI 语法,而是文档站点为支持自定义类名前缀预留的占位符:站点在展示代码时,通过 actions.svelte.js 中的 prefixClassNames 指令把代码内的 $$ 实时替换为前缀 store 的当前值;而 PrefixEdit.svelte 提供了输入框,允许读者输入自定义前缀(例如 tw-)后让全部示例代码同步变为 tw-stack。
daisyUI 组件本身默认不带前缀(package.json 中 prefix 默认值为空)。因此:
- 如果你未配置前缀:直接忽略
$$,类名写作stack、stack-top即可,与本文示例一致; - 如果你通过 Tailwind 配置了全局前缀(对应 daisyUI 的
prefix插件选项):把$$替换成你的前缀字符串,文档中的所有示例代码即可原样使用。
小结与相关资源
Stack 用约 80 行 CSS 就完成了一个框架无关、零 JS 的层叠布局能力,其设计可归纳为三层:
- 容器层:
inline-grid+ 五轨栅格产生错位余量; - 方向层:四个修饰符分别改写子元素的栅格轨道,决定“露出边”的方向;
- 层叠层:按 DOM 顺序递增
z值并施加 90%/70% 透明度,塑造厚度感。
想进一步探索,可以在仓库中查看以下位置:
- 组件官方文档与全部示例:
packages/docs/src/routes/(routes)/components/stack/+page.md/components/stack/+page.md>); - 组件真实样式实现:packages/daisyui/src/components/stack.css;
- Agent/LLM 速查版说明:skills/daisyui/components/stack.md;
- 文档代码块的
$$前缀替换机制:packages/docs/src/lib/actions.svelte.js。
若要快速把 Stack 接入你的项目,可参考仓库根目录的 README.md 与 packages/daisyui/README.md 完成 Tailwind 插件安装,随后即可直接使用本文中的类名与示例。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00