transition在@media中无效,因媒体查询切换的是整套规则而非属性值;须用class切换配合transform等可过渡属性实现动画。

纯媒体查询切换卡片布局时,transition 不会生效——这是最常被误踩的坑。响应式变化本身不触发属性重绘,所以你写再多 transition: all 0.3s 在 @media 里也毫无反应。
为什么 @media 中的 transition 完全无效
CSS transition 只对「同一选择器下、属性值发生变更」起作用。而媒体查询启用/禁用规则时,并不是在修改属性值,是在切换整套样式规则。浏览器不会为此触发重绘动画,更不会插帧。
- 错误写法:
@media (max-width: 768px) { .card { transform: scale(0.9); transition: transform 0.3s; } }→ 无动画 - 真正起效的前提:必须靠 class 切换,且该 class 改变的是可过渡属性(如
transform、opacity、max-height) - 断点只负责“决定加哪个 class”,动画逻辑必须完全剥离到 class 规则中
用 class + transform 实现卡片缩放与位移平滑过渡
比起改 width 或 grid-template-columns,用 transform 做响应式变换更可靠:硬件加速、不触发回流、支持任意断点精度。
- 基础结构:给卡片容器加
data-breakpoint属性或统一 class,比如.card--mobile/.card--tablet - 关键 CSS:
.card { transition: transform 0.35s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.35s; } - 断点适配示例:
.card--mobile { transform: scale(0.85) translateY(4px); opacity: 0.92; },.card--desktop { transform: scale(1) translateY(0); opacity: 1; } - 注意:不要依赖 JS 动态计算 scale 值,提前在 CSS 里写死各断点下的 transform,由 JS 仅负责 class 切换
用 JS 监听 resize 并精准切换 class
不能靠 window.matchMedia 的一次性判断,要防抖 + 节流,否则快速拖拽窗口会反复触发重排。
- 监听函数需用
requestAnimationFrame包裹,避免 layout thrashing - 推荐阈值判断方式:
if (window.innerWidth - 切换前先移除所有相关 class:
el.classList.remove('card--mobile', 'card--tablet', 'card--desktop');,再添加目标 class - 首次加载也要执行一次判断,否则首屏无 class 导致无过渡
用 container queries 替代部分视口断点(现代方案)
如果卡片嵌套在可变宽容器中(如侧边栏、模态框),视口断点会失准。此时应优先用 @container,但要注意兼容性。
- 需给卡片父容器设
container-type: inline-size;,并确保它有明确宽度限制(如max-width: 600px) - 动画仍走 class +
transform路线:@container (max-width: 400px) { .card { --scale: 0.88; } },再用transform: scale(var(--scale));配合 transition - 目前 Safari 16.4+、Chrome 110+、Firefox 119+ 支持,旧版需降级为视口断点 fallback
- 别忘了加
will-change: transform;提升频繁切换场景下的性能
真正难的不是写多少 transition,而是把「布局决策」和「动画执行」彻底解耦——前者交给媒体查询或容器查询,后者只认 class 和可过渡属性。漏掉这个分层,再多的缓动函数都救不回卡顿或闪跳。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











