必须显式声明 transition 才能平滑变色;.card:hover 易被覆盖,需提升选择器权重;父容器 overflow: hidden 会裁剪阴影;移动端不触发 :hover,不可依赖其做核心交互。
直接加 .card:hover { background-color: #f8f9fa; box-shadow: 0 0.5rem 1rem rgba(0,0,0,.15); } 是无效的——缺过渡、被覆盖、父容器裁剪、移动端不触发,四个环节漏一个就白写。
必须显式声明 transition 才能平滑变色
Bootstrap 5 的 .card 默认没写 transition,哪怕你写了 hover 状态,浏览器也不会“滑动”变色或投影,要么卡顿跳变,要么 Safari 直接忽略。
- 在
.card常态规则里必须加:transition: background-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out; - 别用
transition: all——它会把border、outline甚至margin变化也纳入过渡,干扰焦点感知 - 如果只想要背景色渐变,而投影是“开/关”式切换(非渐进加深),可只过渡
background-color,投影用box-shadow: 0 0 0 transparent初始值保兼容
.card:hover 样式被覆盖?提升选择器权重
Bootstrap 5 的 .card 自带 background-color: var(--bs-card-bg) 和 box-shadow: 0 0 0 rgba(0,0,0,0),这两条声明优先级高,纯 .card:hover 很可能被覆盖。
- 调试阶段可用
!important快速验证是否为权重问题:.card:hover { background-color: #e9ecef !important; box-shadow: 0 0.5rem 1rem rgba(0,0,0,.15) !important; } - 上线前务必改用更具体选择器,例如:
.card.card-hoverable:hover,并在 HTML 中加class="card-hoverable" - 若卡片在
.card-group内,它自带overflow: hidden,会直接砍掉投影——此时再高的选择器权重也没用
阴影被裁掉?检查父容器 overflow 和 z-index
box-shadow 绘制在盒模型外部,只要祖先元素设了 overflow: hidden(比如 .row、.container-fluid、自定义 wrapper),阴影就会被硬裁切,和 CSS 权重无关。
- 看阴影是否刚好卡在 outline 边上,就是这个原因
- 稳妥解法:删掉或改为
overflow: visible;若结构受限,给.card加position: relative; z-index: 1;,并确认无兄弟元素用更高z-index盖住它 - 特别注意
.card-group——它内部强制overflow: hidden,想保留阴影就得换布局,用.row + .col或 Flex 容器替代
移动端点按不触发 :hover?别依赖它做核心交互
iOS Safari 和 Android Chrome 在真实设备上,单次点击不会触发 :hover,这是规范行为,不是 bug。如果你依赖“点一下变色+投影”来暗示可交互,纯 CSS 方案不可靠。
- 视觉反馈建议降级为
:active(点击瞬间)或配合 JS 添加临时 class - 对无障碍友好:确保关键操作不依赖悬停状态,比如链接、按钮应有明确文字或图标提示
- 真要统一体验,建议用
pointer-events: none配合媒体查询屏蔽桌面端 hover 干扰,或用@media (hover: hover)做条件加载
最常被忽略的是父容器 overflow: hidden 和移动端无 :hover 触发这两个点——前者让效果完全不可见,后者让真机用户根本看不到你写的动画。











