@media 使用技巧
一、基础语法
css
@media <媒体类型> and (<条件1>) and (<条件2>) {
/* 样式 */
}媒体类型(通常省略,默认 all):
screen— 屏幕print— 打印all— 所有设备
二、常用条件特性
1. 宽度相关
css
/* 精确宽度(少用) */
@media (width: 768px) { }
/* 最大宽度:<= 768px 生效(Desktop First) */
@media (max-width: 768px) { }
/* 最小宽度:>= 768px 生效(Mobile First) */
@media (min-width: 768px) { }
/* 范围:768px ~ 1024px */
@media (min-width: 768px) and (max-width: 1024px) { }2. 新范围语法(Media Queries Level 4)
更直观的写法,现代浏览器均已支持:
css
/* 等价于 max-width: 768px */
@media (width <= 768px) { }
/* 等价于 min-width: 768px */
@media (width >= 768px) { }
/* 等价于 min-width: 768px and max-width: 1024px */
@media (768px <= width <= 1024px) { }3. 高度相关
css
/* 矮屏幕(如横屏手机) */
@media (max-height: 500px) {
.header { padding: 4px 16px; }
}4. 屏幕方向
css
/* 竖屏 */
@media (orientation: portrait) {
.grid { grid-template-columns: 1fr; }
}
/* 横屏 */
@media (orientation: landscape) {
.grid { grid-template-columns: 1fr 1fr; }
}5. 交互能力检测
css
/* 有鼠标悬停能力的设备(PC) */
@media (hover: hover) and (pointer: fine) {
.btn:hover { background: #333; }
.tooltip { display: block; }
}
/* 触屏设备(手机/平板) */
@media (hover: none) and (pointer: coarse) {
.btn { min-height: 48px; } /* 增大触摸区域 */
}| 特性 | fine | coarse |
|---|---|---|
hover: hover | PC 鼠标 | — |
hover: none | — | 手机/平板触屏 |
pointer: fine | 鼠标精确指针 | — |
pointer: coarse | — | 手指粗略指针 |
6. 高分辨率屏幕(Retina)
css
@media (min-resolution: 2dppx) {
.logo { background-image: url('logo@2x.png'); }
}
/* 等价的旧写法 */
@media (-webkit-min-device-pixel-ratio: 2) {
.logo { background-image: url('logo@2x.png'); }
}7. 用户偏好
css
/* 深色模式 */
@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a1a;
--text: #e0e0e0;
}
}
/* 浅色模式 */
@media (prefers-color-scheme: light) {
:root {
--bg: #ffffff;
--text: #333333;
}
}
/* 减少动画(无障碍) */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
/* 低数据流量模式 */
@media (prefers-reduced-data: reduce) {
.hero-video { display: none; }
.hero-image { display: block; }
}三、逻辑运算符
and — 同时满足
css
@media (min-width: 768px) and (orientation: landscape) { },(逗号)— 或(满足任一)
css
/* 宽度 <= 480px 或 横屏时 */
@media (max-width: 480px), (orientation: landscape) { }not — 取反(对整条规则取反)
css
/* 非打印设备 */
@media not print { }
/* 注意:not 作用于整条,加括号更清晰 */
@media not (hover: hover) {
/* 没有悬停能力的设备 */
}only — 防旧浏览器误读
css
@media only screen and (max-width: 768px) { }四、Mobile First vs Desktop First
Mobile First(推荐)
先写手机样式,用 min-width 向上增强:
css
/* 基础:手机 */
.sidebar { display: none; }
.content { padding: 12px; }
/* >= 768px:平板 */
@media (min-width: 768px) {
.sidebar { display: block; width: 200px; }
.content { padding: 24px; }
}
/* >= 1200px:桌面 */
@media (min-width: 1200px) {
.sidebar { width: 280px; }
.content { padding: 32px; }
}Desktop First
先写桌面样式,用 max-width 向下覆盖:
css
/* 基础:桌面 */
.sidebar { width: 280px; }
/* <= 1024px */
@media (max-width: 1024px) {
.sidebar { width: 200px; }
}
/* <= 768px */
@media (max-width: 768px) {
.sidebar { display: none; }
}建议:新项目用 Mobile First。手机端通常更简单,逐步增强比逐步削减更容易维护。
五、断点管理技巧
1. 用 CSS 变量 + 统一断点
CSS 自身不支持变量作为媒体查询值,但可以用 SCSS/Less 统一管理:
scss
// _breakpoints.scss
$bp-mobile: 480px;
$bp-tablet: 768px;
$bp-desktop: 1024px;
$bp-wide: 1440px;
@mixin mobile { @media (max-width: #{$bp-tablet - 1}) { @content; } }
@mixin tablet { @media (min-width: $bp-tablet) and (max-width: #{$bp-desktop - 1}) { @content; } }
@mixin desktop { @media (min-width: $bp-desktop) { @content; } }
// 使用
.card {
padding: 12px;
@include tablet { padding: 20px; }
@include desktop { padding: 32px; }
}2. 内容驱动断点
不要盲目使用 768/1024 这些"标准"数字。当布局开始"坏掉"的地方,就是断点:
css
/* 当卡片在 600px 以下挤不下两列时,切换为单列 */
@media (max-width: 600px) {
.card-grid { grid-template-columns: 1fr; }
}六、@media 书写位置
方式一:集中写在底部
css
/* 所有组件样式 */
.header { ... }
.card { ... }
.footer { ... }
/* 底部集中写响应式 */
@media (max-width: 768px) {
.header { ... }
.card { ... }
.footer { ... }
}方式二:跟随组件就近写(推荐)
css
.header { padding: 16px 32px; }
@media (max-width: 768px) {
.header { padding: 8px 16px; }
}
.card { display: grid; grid-template-columns: 1fr 1fr; }
@media (max-width: 768px) {
.card { grid-template-columns: 1fr; }
}就近写的好处:修改某个组件时,所有相关的响应式规则都在旁边,维护更方便。浏览器会自动合并重复的
@media块,不影响性能。
七、打印样式
css
@media print {
/* 隐藏不需要打印的元素 */
.navbar, .sidebar, .footer, .no-print {
display: none !important;
}
/* 全宽显示内容 */
.content {
width: 100%;
margin: 0;
padding: 0;
}
/* 显示链接地址 */
a[href]::after {
content: " (" attr(href) ")";
font-size: 0.8em;
color: #666;
}
/* 避免在元素中间分页 */
.card, img, table {
break-inside: avoid;
}
}八、@container 查询(补充)
@media 基于视口,@container 基于父容器,用于组件级响应式:
css
.card-wrapper {
container-type: inline-size;
container-name: card;
}
/* 当 card-wrapper 宽度 <= 400px 时 */
@container card (max-width: 400px) {
.card {
flex-direction: column;
}
.card-image {
width: 100%;
}
}
@container card (min-width: 401px) {
.card {
flex-direction: row;
}
.card-image {
width: 40%;
}
}
@media适合页面级布局切换,@container适合可复用组件的自适应。两者配合使用效果最佳。
速查表
| 需求 | 写法 |
|---|---|
| 手机端 | @media (max-width: 768px) 或 (width <= 768px) |
| 平板竖屏 | @media (min-width: 768px) and (max-width: 1024px) and (orientation: portrait) |
| 桌面端 | @media (min-width: 1024px) |
| 深色模式 | @media (prefers-color-scheme: dark) |
| 触屏设备 | @media (hover: none) and (pointer: coarse) |
| Retina 屏 | @media (min-resolution: 2dppx) |
| 减少动画 | @media (prefers-reduced-motion: reduce) |
| 打印 | @media print |
| 横屏 | @media (orientation: landscape) |
