仅 CSS Tailwind CSS 模态使用原生 <dialog> 元素。响应式大小、背景和焦点陷阱。没有用于基本使用的 JavaScript。 WCAG AA 可访问,可与 Django、HTMX、Laravel、React 和任何堆栈配合使用。
模态组件在聚焦的覆盖窗口中显示重要信息或请求用户操作。模态基于语义 HTML 对话框元素构建,支持动画、可自定义定位和背景覆盖。 Frutjam 模态系统可通过键盘导航和陷阱焦点完全访问,使其成为确认、表单和警报对话框的理想选择。
仅 CSS,无需 JavaScript。 WCAG AA 可访问且与框架无关 - 可与 Django、HTMX、Laravel、React 和任何堆栈配合使用。
| 班级 | 类型 | 描述 |
|---|---|---|
| modal | 根据 | 全屏对话框覆盖容器 |
| modal-content | 修饰符 | 带填充和背景的内面板 |
| modal-backdrop | 修饰符 | 点击关闭背景覆盖 |
| modal-top | 修饰符 | 将内容与屏幕顶部对齐 |
| modal-bottom | 修饰符 | 将内容与屏幕底部对齐 |
| modal-start | 修饰符 | 将内容左对齐 |
| modal-end | 修饰符 | 将内容右对齐 |
| modal-center | 修饰符 | 水平居中 |
| modal-middle | 修饰符 | 垂直居中 |
| modal-slide-up | 风格 | 上滑入口动画 |
| modal-slide-down | 风格 | 下滑入口动画 |
| modal-slide-start | 风格 | 从左侧滑入动画 |
| modal-slide-end | 风格 | 从右侧动画滑入 |
基本用法
将唯一的 ID 添加到 <dialog id="myModal"> HTML 元素,然后在 JavaScript 中使用该 id 调用 myModal.showModal() 打开模式,并使用 myModal.close() 关闭模式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <dialog class="modal modal-center lg:modal-middle modal-slide-end lg:modal-slide-down" id="toggleModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Dialog modal</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="toggleModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Press Esc key or close button to close the modal</p> </div> <button type="button" class="modal-backdrop" onclick="toggleModal.close()">Close Modal via Backdrop</button> </dialog> <button type="button" class="btn btn-xs" onclick="toggleModal.showModal()">Show Modal</button> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import { useModal } from 'frutjam/react' export default function ModalDemo() { const modal = useModal() return ( <> <button type="button" className="btn btn-xs" onClick={modal.open}>Show Modal</button> <dialog ref={modal.ref} className="modal modal-center lg:modal-middle modal-slide-end lg:modal-slide-down"> <div className="modal-content"> <div className="flex justify-between items-center gap-3"> <div className="font-medium heading-lg">Dialog modal</div> <button type="button" className="btn btn-xs btn-square btn-rounded btn-ghost" onClick={modal.close}> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div className="divider my-3"></div> <p className="para">Press Esc key or close button to close the modal</p> </div> <button type="button" className="modal-backdrop" onClick={modal.close}>Close Modal via Backdrop</button> </dialog> </> ) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <script setup> import { ref } from 'vue' const dialogRef = ref(null) </script> <template> <button type="button" class="btn btn-xs" @click="dialogRef.showModal()">Show Modal</button> <dialog ref="dialogRef" class="modal modal-center lg:modal-middle modal-slide-end lg:modal-slide-down"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Dialog modal</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" @click="dialogRef.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Press Esc key or close button to close the modal</p> </div> <button type="button" class="modal-backdrop" @click="dialogRef.close()">Close Modal via Backdrop</button> </dialog> </template> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <script> let dialog = $state(null) </script> <button type="button" class="btn btn-xs" onclick={() => dialog.showModal()}>Show Modal</button> <dialog bind:this={dialog} class="modal modal-center lg:modal-middle modal-slide-end lg:modal-slide-down"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Dialog modal</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick={() => dialog.close()}> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Press Esc key or close button to close the modal</p> </div> <button type="button" class="modal-backdrop" onclick={() => dialog.close()}>Close Modal via Backdrop</button> </dialog> |
单击外部时关闭模态
.modal-backdrop 提供了一个可点击的背景,当在模态内容之外单击时,该背景会关闭模态。
1 2 3 4 5 6 7 8 9 10 11 12 13 | <dialog class="modal" id="backdropModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Dialog modal</div> </div> <div class="divider my-3"></div> <p class="para">Press Esc key or click outside to close the modal</p> </div> <button type="button" class="modal-backdrop" onclick="backdropModal.close()"> Close Modal via Backdrop </button> </dialog> <button type="button" class="btn btn-xs" onclick="backdropModal.showModal()">Show Modal</button> |
模态幻灯片动画
使用模态组件中的以下定向实用程序类,从顶部、底部、开始(LTR 中向左、RTL 中向右)或结束(LTR 中向右、RTL 中向左)平滑滑入和滑出:modal-slide-top、modal-slide-bottom、modal-slide-start 和 modal-slide-end。这些动画通过使用基于模态位置的动态过渡来改善用户体验。
从头开始模态幻灯片(水平)
添加 modal-slide-start 实用程序以从起始侧水平滑动模态;在从左到右 (LTR) 布局中,它从左侧出现;在从右到左 (RTL) 布局中,它从右侧出现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <dialog class="modal modal-center lg:modal-middle modal-slide-start" id="slideStartModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Slide start modal</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="slideStartModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Horizontally slides the modal in and out from the start side.</p> </div> </dialog> <button type="button" class="btn btn-xs" onclick="slideStartModal.showModal()">Show Modal</button> |
从末端开始模态滑动(水平)
在模态组件中添加 modal-slide-end 实用程序,使模态从末端水平滑动;在从左到右 (LTR) 布局中,它从右侧出现;在从右到左 (RTL) 布局中,它从左侧出现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <dialog class="modal modal-center lg:modal-middle modal-slide-end" id="slideEndModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Slide end modal</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="slideEndModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Horizontally slides the modal in and out from the end side.</p> </div> </dialog> <button type="button" class="btn btn-xs" onclick="slideEndModal.showModal()">Show Modal</button> |
从底部滑动(垂直):modal-slide-up
方向:从底部垂直滑入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <dialog class="modal modal-center lg:modal-middle modal-slide-up" id="slideUpModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Slide up modal</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="slideUpModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Vertically slides the modal in and out from the bottom.</p> </div> </dialog> <button type="button" class="btn btn-xs" onclick="slideUpModal.showModal()">Show Modal</button> |
从顶部滑动(垂直)
在模态组件中添加 modal-slide-down 实用程序以从顶部垂直滑入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <dialog class="modal modal-center lg:modal-middle modal-slide-down" id="slideDownModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Slide down modal</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="slideDownModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Vertically slides the modal in and out from the top.</p> </div> </dialog> <button type="button" class="btn btn-xs" onclick="slideDownModal.showModal()">Show Modal</button> |
用于通知的滑动动画模式的示例用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <dialog class="modal modal-end modal-top modal-slide-end" id="notificationSlideModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Notification modal</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="notificationSlideModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> </div> </dialog> <button type="button" class="btn btn-xs" onclick="notificationSlideModal.showModal()">Show Modal</button> |
模态展示位置
默认情况下,模态组件位于屏幕中央,但可以根据使用情况使用水平类 modal-start、modal-center 或 modal-end 以及垂直类 modal-top、modal-middle 或 modal-bottom 进行放置。布局的设计考虑了 RTL 和 LTR 兼容性,使模式能够适应不同的语言方向和布局。
使用modal-start、modal-center或modal-end进行水平放置,使用modal-top、modal-middle或modal-bottom进行垂直放置。这些类应用于模态组件。
左上角模态位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <dialog class="modal modal-start modal-top" id="topLeftModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Modal placement top left</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="topLeftModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Modal placed at the top left corner of the screen</p> </div> <button type="button" class="modal-backdrop" onclick="topLeftModal.close()"> Close Modal via Backdrop </button> </dialog> <button type="button" class="btn btn-xs" onclick="topLeftModal.showModal()">Show Modal</button> |
顶部中心模态放置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <dialog class="modal modal-center modal-top" id="topCenterModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Modal placement top center</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="topCenterModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Modal placed at the top center corner of the screen</p> </div> <button type="button" class="modal-backdrop" onclick="topCenterModal.close()"> Close Modal via Backdrop </button> </dialog> <button type="button" class="btn btn-xs" onclick="topCenterModal.showModal()">Show Modal</button> |
右上角模态位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <dialog class="modal modal-end modal-top" id="topEndModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Modal placement top end</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="topEndModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Modal placed at the top end corner of the screen</p> </div> <button type="button" class="modal-backdrop" onclick="topEndModal.close()"> Close Modal via Backdrop </button> </dialog> <button type="button" class="btn btn-xs" onclick="topEndModal.showModal()">Show Modal</button> |
居中左模态放置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <dialog class="modal modal-start modal-middle" id="startCenterModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Modal placement left center</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="startCenterModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Modal placed at the start center corner of the screen</p> </div> <button type="button" class="modal-backdrop" onclick="startCenterModal.close()"> Close Modal via Backdrop </button> </dialog> <button type="button" class="btn btn-xs" onclick="startCenterModal.showModal()">Show Modal</button> |
居中右模态放置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <dialog class="modal modal-end modal-middle" id="endCenterModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Modal placement right center</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="endCenterModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Modal placed at the end center corner of the screen</p> </div> <button type="button" class="modal-backdrop" onclick="endCenterModal.close()"> Close Modal via Backdrop </button> </dialog> <button type="button" class="btn btn-xs" onclick="endCenterModal.showModal()">Show Modal</button> |
左下角模态位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <dialog class="modal modal-start modal-bottom" id="bottomStartModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Modal placement bottom start</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="bottomStartModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Modal placed at the bottom start corner of the screen</p> </div> <button type="button" class="modal-backdrop" onclick="bottomStartModal.close()"> Close Modal via Backdrop </button> </dialog> <button type="button" class="btn btn-xs" onclick="bottomStartModal.showModal()">Show Modal</button> |
底部中心模态放置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <dialog class="modal modal-center modal-bottom" id="bottomCenterModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Modal placement bottom center</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="bottomCenterModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Modal placed at the bottom center corner of the screen</p> </div> <button type="button" class="modal-backdrop" onclick="bottomCenterModal.close()"> Close Modal via Backdrop </button> </dialog> <button type="button" class="btn btn-xs" onclick="bottomCenterModal.showModal()">Show Modal</button> |
右下模态位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <dialog class="modal modal-end modal-bottom" id="bottomEndModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Modal placement bottom center</div> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="bottomEndModal.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 6 6 18"></path> <path d="m6 6 12 12"></path> </svg> </button> </div> <div class="divider my-3"></div> <p class="para">Modal placed at the bottom center corner of the screen</p> </div> <button type="button" class="modal-backdrop" onclick="bottomEndModal.close()"> Close Modal via Backdrop </button> </dialog> <button type="button" class="btn btn-xs" onclick="bottomEndModal.showModal()">Show Modal</button> |
桌面和移动屏幕的模态响应式定位
根据您的使用案例,您可以将模态框放置在桌面或移动设备上的任何位置,例如桌面中心和移动设备顶部中心。
1 2 3 4 5 6 7 8 9 10 11 12 13 | <dialog class="modal modal-center modal-top lg:modal-center lg:modal-middle" id="responsiveModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Responsive modal</div> </div> <div class="divider my-3"></div> <p class="para">Resize the modal to a small screen to see the change in modal position.</p> </div> <button type="button" class="modal-backdrop" onclick="responsiveModal.close()"> Close Modal via Backdrop </button> </dialog> <button type="button" class="btn btn-xs" onclick="responsiveModal.showModal()">Show Modal</button> |
基于语言方向的模态定位
根据语言方向(LTR 或 RTL)将模态框放置在屏幕上的任意位置。
LTR 和 RTL 中右对齐且垂直居中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <dialog class="modal ltr:modal-end ltr:modal-middle rtl:modal-start lg:modal-middle" id="ltrModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Responsive modal</div> </div> <div class="divider my-3"></div> <p class="para"> Changing <code>dir="rtl"</code> in the HTML will have no effect on the modal's the position because the layout is controlled by utility classes: <code>modal-end</code> for the LTR variant and <code>modal-start</code> for the RTL variant. </p> </div> <button type="button" class="modal-backdrop" onclick="ltrModal.close()"> Close Modal via Backdrop </button> </dialog> <button type="button" class="btn btn-xs" onclick="ltrModal.showModal()">Show Modal</button> |
根据屏幕尺寸和语言方向放置模态框
1 2 3 4 5 6 7 8 9 10 11 12 13 | <dialog class="modal ltr:modal-center lg:ltr:modal-start ltr:modal-top lg:ltr:modal-middle rtl:modal-center lg:rtl:modal-start rtl:modal-bottom lg:rtl:modal-middle" id="mixedModal"> <div class="modal-content"> <div class="flex justify-between items-center gap-3"> <div class="font-medium heading-lg">Responsive modal</div> </div> <div class="divider my-3"></div> <p class="para">Change the screen and screen direction to see the change in modal position.</p> </div> <button type="button" class="modal-backdrop" onclick="mixedModal.close()"> Close Modal via Backdrop </button> </dialog> <button type="button" class="btn btn-xs" onclick="mixedModal.showModal()">Show Modal</button> |
使用 Claude Code、Cursor 或其他 AI 编辑器?
Cherry MCP 为您的 AI 编辑器按需提供准确的 莫代尔 类名称和结构。不再有幻觉课程。