3、媒体查询入门:媒体类型、媒体特性、逻辑操作符、断点策略

媒体查询(Media Queries),说白了就是让 CSS 学会「看人下菜碟」。

你写一套样式,它能在手机上是竖排布局,到了平板变成两栏,到了桌面变成三栏。这一切的核心,就是 @media 这个规则。

我记得刚入行那会儿,做响应式全靠 JS 判断窗口宽度,然后动态加载不同的 CSS 文件。那叫一个痛苦。后来 CSS3 把媒体查询标准化了,前端适配才真正有了「正规军」。

3.1 媒体类型:你适配的是什么设备?

媒体类型是最早的适配手段。它告诉浏览器:我这套样式是写给哪种设备看的。

媒体类型 说明 实际使用频率
all 所有设备(默认值) 极高
screen 电脑屏幕、手机、平板等 极高
print 打印机或打印预览 中等
speech 屏幕阅读器等语音设备 低
我的习惯:绝大多数场景只用 screen 和 all。打印样式单独写一个 @media print 就够了。至于 speech,说实话我做了这么多年项目,几乎没用过。
/* 基础写法 */
@media screen {
  body {
    font-size: 16px;
  }
}

/* 打印样式:隐藏导航和广告 */
@media print {
  .nav,
  .sidebar,
  .ad-banner {
    display: none;
  }
  body {
    font-size: 12pt;
  }
}

3.2 媒体特性:精确控制适配条件

媒体类型太粗了。你没法区分「这是个手机还是个平板」。所以我们需要媒体特性(Media Features)。

最常用的就是 width 和 height,但实际项目中我几乎只用 min-width 和 max-width。为什么?因为设备宽度千差万别,用精确值去匹配根本不现实。

核心原则:永远用 min-width 做「向上兼容」,用 max-width 做「向下兼容」。不要用精确的 width: 375px 去匹配 iPhone。

除了宽高,还有几个特性值得关注:

  • orientation:横屏(landscape)还是竖屏(portrait)。我在做视频类 App 的 H5 页面时,经常用这个特性来调整播放器的布局。
  • resolution:屏幕分辨率(dpi/dppx)。用来区分普通屏和 Retina 屏,加载不同精度的图片。
  • hover:设备是否支持悬停。触摸设备不支持 :hover,这个特性可以用来优化交互。
  • pointer:指点设备的精度(fine/coarse)。手机是 coarse,鼠标是 fine。
/* 横屏时放大字体 */
@media screen and (orientation: landscape) {
  body {
    font-size: 18px;
  }
}

/* Retina 屏加载 2x 图片 */
@media screen and (min-resolution: 2dppx) {
  .logo {
    background-image: url('logo@2x.png');
  }
}

/* 触摸设备去掉 hover 效果 */
@media (hover: none) {
  .button:hover {
    background-color: initial;
  }
}
我曾经踩过的坑:在 Android 某些旧版本浏览器上,resolution 的单位不支持 dppx,只认 dpi。所以稳妥的做法是同时写两个单位做 fallback。

3.3 逻辑操作符:组合你的适配条件

单个条件不够用?那就用逻辑操作符把它们组合起来。

操作符 含义 示例
and 与(所有条件都满足) @media screen and (min-width: 768px)
,(逗号) 或(满足任一条件) @media (max-width: 600px), (orientation: portrait)
not 非(取反) @media not print
only 仅(防止旧浏览器解析) @media only screen

你想想看,and 和逗号是最常用的。我个人的写法习惯是:

  • 多个条件必须同时满足 → 用 and
  • 多个条件满足任意一个即可 → 用逗号
  • 需要排除某种设备 → 用 not
/* 屏幕设备 + 宽度在 768px 到 1024px 之间 */
@media screen and (min-width: 768px) and (max-width: 1024px) {
  .container {
    width: 90%;
  }
}

/* 手机竖屏 或 平板横屏 */
@media (max-width: 480px), (min-width: 768px) and (orientation: landscape) {
  .menu {
    display: block;
  }
}

/* 排除打印设备 */
@media not print {
  .header {
    position: sticky;
    top: 0;
  }
}
一个小细节:only 操作符在现在基本用不到了。它是用来让不支持媒体查询的旧浏览器忽略整个规则的。现在谁还用 IE8 呢?我反正是直接省略。

3.4 断点策略:怎么选断点?

断点(Breakpoint)是媒体查询里最让人纠结的事。选多了,维护成本高;选少了,适配效果差。

我见过两种主流策略:

策略一:以设备为基准

直接拿主流设备的宽度当断点。比如 iPhone 的 375px、iPad 的 768px、桌面 1024px。

  • 优点:简单粗暴,容易理解
  • 缺点:设备更新太快,今天 iPhone 13 是 390px,明天 iPhone 14 就变 430px 了,你改不改?

策略二:以内容为基准

不管设备长什么样,只关注你的布局在什么宽度下会「崩掉」。在那个临界点设置断点。

  • 优点:一劳永逸,设备怎么变都不怕
  • 缺点:需要反复调试,前期工作量大
我的建议:用策略二。别去记什么 iPhone 宽度、三星宽度。打开浏览器,慢慢拖拽窗口,看到布局变形了,就在那个位置加一个断点。这才是真正的「内容驱动适配」。

下面是我个人常用的断点体系,供你参考:

/* 手机:默认样式(0 - 575px) */
/* 不用写媒体查询,直接写基础样式 */

/* 大屏手机/小平板:576px 起 */
@media (min-width: 576px) {
  ...
}

/* 平板:768px 起 */
@media (min-width: 768px) {
  ...
}

/* 小桌面:992px 起 */
@media (min-width: 992px) {
  ...
}

/* 大桌面:1200px 起 */
@media (min-width: 1200px) {
  ...
}

/* 超大屏:1400px 起 */
@media (min-width: 1400px) {
  ...
}
注意:断点不是越多越好。我见过有人写了 15 个断点,结果改一个间距要改 15 个地方。一般来说,3 到 5 个断点足够覆盖绝大多数场景了。

3.5 知识体系总览

下面这张图把媒体查询的核心知识点串起来了。你可以把它当作一个快速索引。

媒体查询知识体系 @media 媒体查询 媒体类型 all / screen print / speech (最常用:screen) 媒体特性 min-width / max-width orientation resolution hover / pointer 逻辑操作符 and(与) ,(或) not(非) 断点策略 以设备为基准 ❌ 以内容为基准 ✅ (推荐 3~5 个断点)

3.6 写在最后

媒体查询不难,但它是整个设备端适配的基石。你后面学到的 rem、vw、flex、grid,最终都要和媒体查询配合使用。

嗯,这里要注意一点:别一上来就写一堆 @media。先写基础样式(手机优先),再逐步用 min-width 往上叠加。这样代码更干净,也更容易维护。

我个人习惯把媒体查询写在对应选择器的附近,而不是单独放在文件末尾。这样改一个组件的时候,不用上下翻找,效率高很多。