bootstrap 5 的纯 css 交互仅适用于单向、无状态的简单显隐或样式切换,如:hover 卡片上浮、:focus 表单高亮、:checked 开关等;但下拉菜单等需 aria 同步、键盘导航及 popper 定位的组件必须依赖 js,否则将导致移动端常驻、定位失效与无障碍失能。

Bootstrap 5 本身已移除 jQuery 依赖,但它的很多交互(如下拉菜单、折叠、模态框)仍需 JS 初始化和状态管理;纯 CSS 实现“无 JS 交互”仅适用于有限场景,且必须接受功能妥协——比如放弃键盘可访问性、移动端兼容性或状态同步。
哪些交互能用纯 CSS 完全替代
只有满足「单向、无状态、不依赖 DOM 位置计算、不需 ARIA 同步」的简单显隐/样式切换才适合纯 CSS:
-
:hover触发的卡片上浮(transform: translateY(-6px))、按钮变色、下划线动画 -
:focus或:focus-within触发的表单高亮、输入框边框强化 -
:checked+ 隐藏<input type="checkbox">实现的开关、手风琴折叠(需结构配合) -
@media (hover: hover) and (pointer: fine)条件下启用的桌面专属悬停效果
别试图用 :hover 替代 .dropdown 的展开逻辑——它无法同步 aria-expanded,也不能让键盘用户按 Tab 进入子菜单。
为什么 .dropdown-menu:hover 不行
直接写 .dropdown:hover .dropdown-menu { display: block; } 看似简单,但会立刻暴露三个硬伤:
- 移动端点击后菜单常驻不收起:触屏设备没有真正
hover状态,:hover在轻点后被触发,却无对应:hover-out机制 - Popper 定位失效:
display: block绕过 Bootstrap 的 JS 定位逻辑,菜单可能出现在左上角或被裁剪 - 焦点与屏幕阅读器失联:JS 不知道菜单开了,
aria-expanded="false"保持不变,视障用户无法感知
真要免 JS,唯一可行路径是改用 <details>/<summary></summary></details> 语义化原生标签,再用 CSS 覆盖样式——但它不支持二级嵌套,也不兼容 Bootstrap 的栅格对齐。
transition 必须配可动画属性,否则白写
Bootstrap 5 的组件大量依赖 display 控制显隐(如 .dropdown-menu、.collapse),而 display 无法参与 transition。想加动画,必须换属性:
- 用
opacity+visibility:适合淡入淡出,但隐藏时仍占布局空间 - 用
max-height:设初始max-height: 0,展开时设为足够大的值(如max-height: 300px),需确保内容不超过该值 - 用
transform: scaleY(0)+overflow: hidden:最干净,但 Safari 偶尔首帧跳变,可加will-change: transform缓解
所有方案都必须把 transition 写在常态选择器里(如 .dropdown-menu),而不是只写在 .show 或 :hover 中,否则首次展开无动画。
移动端 fallback 必须手动补,CSS 无法自动降级
@media (hover: hover) 在 iOS Safari 真机上大概率返回 false,不能靠它做兜底。纯 CSS 方案在触屏设备上天然失效,你得主动提供替代路径:
- 给卡片加
tabindex="0",再写.card:focus { transform: translateY(-6px); },兼顾键盘与触摸聚焦 - 下拉主链接保留
href="#",不删掉,确保点击有反馈;用 JS 检测touchstart后禁用悬停逻辑,但这是 JS 行为,已超出纯 CSS 范畴 - 所有纯 CSS 悬停效果旁,必须配一个非悬停的入口(如「菜单」文字按钮),否则触屏用户完全不可达
真正容易被忽略的是:纯 CSS 交互一旦上线,就等于放弃了 WCAG 2.1 中 “键盘可操作” 和 “状态可感知” 两条核心要求——这不是技术限制,是设计取舍。如果项目需要合规,JS 就不是可选项,而是必选项。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











