4、媒体查询进阶:断点策略
媒体查询这东西,入门容易,用好难。我见过太多同学写了满屏的 @media,结果一换设备就崩。问题出在哪?说白了,就是断点没定好。
今天咱们聊聊断点策略。这东西决定了你的页面在不同屏幕上的表现。选对了,事半功倍;选错了,改到怀疑人生。
Mobile First vs Desktop First
这两种策略,我一开始也纠结过。后来踩了坑才明白,它们各有各的适用场景。
Mobile First,就是先写手机端的样式,再用媒体查询逐步增强。代码长这样:
/* 默认:手机端样式 */
.container {
width: 100%;
padding: 0 15px;
}
/* 平板:宽度超过768px时生效 */
@media (min-width: 768px) {
.container {
width: 750px;
margin: 0 auto;
}
}
/* 桌面:宽度超过992px时生效 */
@media (min-width: 992px) {
.container {
width: 970px;
}
}
你看,用的是 min-width。从小往大写,像盖楼一样,一层层往上加。
Desktop First 反过来,先写桌面端,再用媒体查询降级:
/* 默认:桌面端样式 */
.container {
width: 970px;
margin: 0 auto;
}
/* 平板:宽度小于992px时生效 */
@media (max-width: 991px) {
.container {
width: 750px;
}
}
/* 手机:宽度小于768px时生效 */
@media (max-width: 767px) {
.container {
width: 100%;
padding: 0 15px;
}
}
这里用的是 max-width。从大往小写,像拆积木一样,一层层拆掉。
我个人习惯:新项目用 Mobile First。为什么?因为现在移动端流量占比太大了。你想想看,用户掏出手机看你的页面,结果加载了一堆桌面端的样式,再被媒体查询覆盖掉,多浪费性能。
但 Desktop First 也不是一无是处。我在做后台管理系统时,就经常用 Desktop First。因为后台用户基本都在电脑上操作,手机端只是偶尔看看。这时候先保证桌面体验,再适配手机,反而更合理。
小技巧:不确定选哪个?看看你的用户画像。如果移动端用户多,选 Mobile First;如果桌面端用户多,选 Desktop First。别纠结,数据说话。
常见断点设置
断点怎么设?网上有各种推荐值。我直接给你一套我用了三年的方案,稳得很:
| 设备类型 | 断点值 | 说明 |
|---|---|---|
| 手机竖屏 | < 576px | 小屏手机,如 iPhone SE |
| 手机横屏 | ≥ 576px | 大屏手机横过来看 |
| 平板竖屏 | ≥ 768px | iPad 竖屏状态 |
| 平板横屏/小桌面 | ≥ 992px | iPad 横屏或小笔记本 |
| 桌面 | ≥ 1200px | 标准桌面显示器 |
| 大桌面 | ≥ 1400px | 宽屏显示器 |
这套断点,我参考了 Bootstrap 的体系,但做了微调。为什么是 576、768、992、1200、1400?因为这些值覆盖了市面上绝大多数设备的宽度。
注意:别拿具体设备当断点!我见过有人写 @media (max-width: 375px),因为那是 iPhone X 的宽度。结果 iPhone 12 一出,宽度变了,代码就废了。断点应该基于内容,而不是设备。
使用媒体查询调整布局
布局调整,是媒体查询最常用的场景。我给你看个例子,是我之前做的一个产品列表页:
/* Mobile First 策略 */
/* 手机:单列布局 */
.product-list {
display: grid;
grid-template-columns: 1fr;
gap: 15px;
}
/* 平板:两列布局 */
@media (min-width: 768px) {
.product-list {
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
}
/* 桌面:三列布局 */
@media (min-width: 992px) {
.product-list {
grid-template-columns: repeat(3, 1fr);
gap: 30px;
}
}
/* 大桌面:四列布局 */
@media (min-width: 1200px) {
.product-list {
grid-template-columns: repeat(4, 1fr);
}
}
你看,从 1 列到 4 列,随着屏幕变宽,内容越来越多。这就是 Mobile First 的精髓——从小屏开始,逐步释放能力。
除了网格,导航栏也是重灾区。手机上的汉堡菜单,到了桌面就得展开:
/* 手机:隐藏导航,显示汉堡按钮 */
.nav-menu {
display: none;
}
.nav-toggle {
display: block;
}
/* 桌面:显示导航,隐藏汉堡按钮 */
@media (min-width: 992px) {
.nav-menu {
display: flex;
}
.nav-toggle {
display: none;
}
}
嗯,这里要注意:display: none 切换时,别忘了考虑可访问性。屏幕阅读器可能读不到隐藏的内容。我一般会配合 aria-hidden 属性一起用。
使用媒体查询调整字体
字体大小,很多人忽略了。你想想看,手机上字太小看不清,桌面上字太大又显得傻。所以字体也得跟着屏幕走。
我常用的方案有两种:
方案一:直接设置不同断点的字号
body {
font-size: 14px; /* 手机端基础字号 */
line-height: 1.6;
}
@media (min-width: 768px) {
body {
font-size: 16px; /* 平板端稍微大一点 */
}
}
@media (min-width: 1200px) {
body {
font-size: 18px; /* 桌面端更大,阅读更舒服 */
}
}
方案二:用视口单位 + 媒体查询兜底
body {
font-size: calc(14px + 0.25vw); /* 随视口宽度微调 */
}
/* 但为了防止太大或太小,用媒体查询兜底 */
@media (max-width: 320px) {
body {
font-size: 12px; /* 极小屏,不能再小了 */
}
}
@media (min-width: 1600px) {
body {
font-size: 20px; /* 超大屏,不能再大了 */
}
}
方案二更灵活,但兼容性要注意。我一般在生产环境用方案一,简单粗暴,不会出幺蛾子。
避坑指南:我曾经在项目里只用 vw 做响应式字体,结果在 4K 屏上,字大得像标题。后来加了 max-font-size 的限制才解决。记住,纯视口单位有风险,一定要设上下限。
还有标题的字体大小,也得跟着变。比如:
h1 {
font-size: 1.5rem; /* 手机端 */
}
@media (min-width: 768px) {
h1 {
font-size: 2rem; /* 平板端 */
}
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem; /* 桌面端 */
}
}
这样做的好处是,标题在手机上不会占满整个屏幕,在桌面上也不会显得小家子气。
好了,断点策略这块,核心就是这些。记住三点:选对策略(Mobile First 还是 Desktop First)、定好断点(别死磕具体设备)、灵活调整(布局和字体都要管)。下次写媒体查询,试试这些思路,你会发现代码清爽很多。