Web前端入门第 47 问:CSS @media 媒体查询不要只会视口宽度适配

@media 媒体查询的出现解决了什么问题?

曾经,一个网页要兼容移动端和 PC 端,前端的代码复杂度嗖嗖嗖的飙升,需要使用多套代码对各种屏幕尺寸做适配。

@media 的出现解决了 CSS 中无法适配设备尺寸的问题,让 CSS 拥有了处理简单逻辑的能力。

媒体查询就像进店试穿衣服一样,穿得上,咱就用这一套;穿不上,咱就换一套;都穿不上,那就还是穿进店时身上这套吧~~

媒体查询

使用媒体查询之前,先要明白 媒体 二字是指的用户软件设备(比如:电脑中浏览器、网页打印预览等)。

媒体查询无法针对某个具体的 HTML 元素做出响应!!

也无法针对特定的硬件设备做出响应(比如:小米手机、苹果手机等)!!

它只能对用户设备的固定特性做出响应(比如浏览器的可视宽度,是否支持鼠标悬停,设备像素密度等)!!

语法

css 复制代码
@media <media-query-list> {
  <rule-list>
}

一个简单示例

查询媒体宽度在某个范围内时,设置不同的背景色:

html 复制代码
<div class="box">
  <div class="child">媒体查询应用</div>
</div>
<style>
.box {
  margin: 20px 0;
  width: 400px;
  border: var(--base-border, 2px solid rgba(255, 71, 87,0.3));
  resize: both;
  overflow: auto;
}
.box .child {
  margin: 10px;
  border: 1px solid #ffa947;
  padding: 10px;
}
@media (max-width: 450px) {
  /* 宽度小于 450px 时,背景色为#ffa947 */
  .box {
    background-color: #ffa947;
  }
}

@media (min-width: 450px) and (max-width: 600px) {
  /* 宽度在 450px 到 600px 之间时,背景色为#ff4757 */
  .box {
    background-color: #ff4757;
  }
}
</style>

效果:

指定媒体类型

以上媒体查询在未指定媒体类型时,默认为 all 全部媒体类型,将会应用于屏幕和打印预览~

可使用关键字指定 screen 指定用于屏幕或 print 指定用于打印。

html 复制代码
<div class="box">
  <div class="child">媒体查询应用</div>
</div>
<style>
.box {
  margin: 20px 0;
  width: 400px;
  border: var(--base-border, 2px solid rgba(255, 71, 87,0.3));
  resize: both;
  overflow: auto;
}
.box .child {
  margin: 10px;
  border: 1px solid #ffa947;
  padding: 10px;
}
@media screen and (max-width: 1200px) {
  /* 指定屏幕设备宽度小于 1200px 时,背景色为#ffa947 */
  .box {
    background-color: #ffa947;
  }
}

@media print {
  /* 指定打印 字体大小 和 字体颜色 */
  .box {
    font-size: 22pt;
    color: red;
  }
}
</style>

可在浏览器中 ctrl + p 查看打印样式:

使用逻辑运算符

使用逻辑运算符 andnotonly,or,可以组合多个媒体查询条件,实现更复杂的逻辑判断。

and 用于多个查询条件同时匹配时才应用样式:

css 复制代码
@media screen and (min-width: 320px) and (max-width: 600px) {
  .box {
    line-height: 3;
  }
}

not 用于查询条件不匹配时才应用样式:

css 复制代码
@media not screen and (min-width: 600px) {
  /* 指定屏幕设备宽度不大于 600px 时,背景色为 #ffa947 */
  .box {
    background-color: #ffa947;
  }
}

only 仅在整个查询匹配时才应用样式。这对于防止较老的浏览器应用所选样式很有用。当不使用 only 时,较老的浏览器会将 screen and (max-width: 500px) 简单地解释为 screen,忽略查询的其余部分,并将其样式应用于所有屏幕。如果使用 only 运算符,则还必须指定媒体类型。 --- 摘自 MDN

css 复制代码
@media only screen and (max-width: 600px) {
  /* 指定屏幕设备宽度小于 600px 时,字体色为 #ff4757 */
  .box {
    color: #ff4757;
  }
}

,or 运算符等价,or 在媒体查询第 4 版中加入,仅 2022 年之后的浏览器支持:

css 复制代码
@media screen, print {
  .box {
    font-size: 28px;
  }
}
@media (not (color)) or (not (hover)) {
  .box {
    font-weight: bold;
  }
}

需特别注意:逻辑运算符后面必须有至少一个空格!!比如 not(hover) 将不生效,必须写成 not (hover)

新语法

媒体查询第 4 版引入了一种新的范围语法,使用此语法需特别注意浏览器兼容性:

支持的运算符有:等于 =、小于 <、 小于等于 <=、大于 >、大于等于 >=

css 复制代码
/* @media (max-width: 600px) { ... } 等价于 */
@media (width <= 600px) {
  .box {
    font-size: 28px;
  }
}

/* @media (min-width: 600px) and (max-width: 1200px) { ... } 等价于 */
@media (600px <= width <= 1200px) {
  .box {
    font-size: 28px;
  }
}

@media screen and (width = 320px) {
  /* 指定屏幕设备宽度等于 320px 时,行高为 10 */
  .box {
    line-height: 10;
  }
}

第 4 版的媒体查询 W3C 参考文档:https://drafts.csswg.org/mediaqueries/

常用媒体特性列表

any-hover

是否有任何可用的输入机制允许用户将鼠标悬停在元素上。有效值: nonehover

width

可视区域的宽度,包括滚动条的宽度。

允许 min-max- 前缀查询范围。

css 复制代码
@media (width: 600px) {}
@media (min-width: 30rem) {}
@media (max-width: 40rem) {}
css 复制代码
@media (any-hover: hover) {
  /* 有鼠标悬停时(比如PC端),字体色为 #ff4757 */
  .box {
    color: #ff4757;
  }
}

height

可视区域的高度。

允许 min-max- 前缀查询范围。

css 复制代码
@media (height: 600px) {}
@media (min-height: 30rem) {}
@media (max-height: 40rem) {}

resolution

输出设备的像素密度。

允许 min-max- 前缀查询范围。

css 复制代码
@media (resolution: 150dpi) {}
@media (min-resolution: 300dpi) {}
@media (max-resolution: 2dpcm) {}

orientation

可视区域的方向。有效值:portrait(纵向:高度大于或等于宽度)、landscape(横向:宽度大于高度)。

css 复制代码
@media (orientation: portrait) {}
@media (orientation: landscape) {}

pointer

主输入机构是否为指针设备,如果是,其准确性如何。有效值:none(不包括定点设备)、coarse(精度有限的定点设备,例如触摸屏上的手指)、fine(精确指针设备,例如鼠标)。

css 复制代码
@media (any-pointer: fine) {}
@media (any-pointer: coarse) {}

hover

输入机制是否允许用户将鼠标悬停在元素上。有效值:none(无法悬停或无法方便地悬停)、hover(可以方便地将鼠标悬停)。

css 复制代码
@media (hover: hover) {}

aspect-ratio

可视区域的宽高纵横比。有效值:4/31.33333

允许 min-max- 前缀查询范围。

css 复制代码
@media (min-aspect-ratio: 8/5) {}
@media (aspect-ratio: 1/1) {}
@media (max-aspect-ratio: 8/5) {}
@media screen and (min-aspect-ratio: 16/9) {}

prefers-color-scheme

检测用户是喜欢浅色还是深色配色方案。 在 Media Queries Level 5 中添加。有效值:light(浅色)、dark(深色)。

css 复制代码
@media (prefers-color-scheme: dark) {}

不常用媒体特性列表

any-pointer

是否有任何可用的输入机制是指针设备。有效值: nonefinecoarse

css 复制代码
@media (any-pointer: fine) {
  /* 至少一个输入机制包括精确指针设备 */
}

@media (any-pointer: coarse) {
  /* 至少一个 input 机制包括精度有限的定点设备 */
}

color

输出设备的每个颜色分量的位数,如果设备不支持输出彩色,则为 0

允许 min-max- 前缀查询范围。

css 复制代码
/* 任何颜色设备 */
@media (color) {}
/* 每个颜色分量至少有8位的颜色设备 */
@media (min-color: 8) {}

color-gamut

用户代理和输出设备支持的颜色的大致范围。有效值:srgbp3rec2020

css 复制代码
@media (color-gamut: srgb) {}

color-index

输出设备的颜色查找表中的条目数,如果设备不使用此类表,则为 0

允许 min-max- 前缀查询范围。

css 复制代码
@media (color-index) {}
@media (min-color-index: 16000) {}

device-posture 实验性

检测设备的当前状态,即可视区域是处于平放状态还是折叠状态。在 Device Posture API 中定义。有效值:continuous 平面屏幕状态、folded 折叠屏幕状态。

css 复制代码
@media (device-posture: folded) and (orientation: landscape) {}
@media (device-posture: continuous) {}

display-mode

应用程序的显示模式:例如,全屏或画中画模式。 在 Media Queries Level 5 中添加。有效值:浏览器 browser、全屏 fullscreen、画中画 picture-in-pictureminimal-uistandalonewindow-controls-overlay

css 复制代码
@media all and (display-mode: fullscreen) {}

dynamic-range

用户代理和输出设备支持的亮度、对比度和颜色深度的组合。在 Media Queries Level 5 中添加。有效值:standard(任何可视设备)、high(支持的亮度、对比度和颜色深度的组合)。

css 复制代码
@media (dynamic-range: standard) {}
@media (dynamic-range: high) {}

forced-colors

检测 User Agent 是否限制调色板。 在 Media Queries Level 5 中添加。有效值:noneactive(强制颜色模式处于活动状态)。

css 复制代码
@media (forced-colors: active) {}

grid

设备是否使用网格屏幕还是点阵屏幕。有效值:01

css 复制代码
@media (grid: 0) {}
@media (grid: 1) {}

inverted-colors

用户代理或底层作系统是否反转了颜色。在 Media Queries Level 5 中添加。有效值:none(颜色正常显示)、inverted(所有像素都已反转)。

css 复制代码
@media (inverted-colors: inverted) {}
@media (inverted-colors: none) {}

monochrome

输出设备的单色帧缓冲区中每像素的位数,如果设备不是单色的,则为 0

允许 min-max- 前缀查询范围。

css 复制代码
@media (monochrome: 0) {}
@media (max-monochrome: 8) {}

overflow-block

输出设备如何处理沿块轴溢出可视区域的内容。有效值:none(不显示溢出内容)、scroll(滚动显示)、optional-pagedpaged

css 复制代码
@media (overflow-block: scroll) {}

overflow-inline

沿内联轴溢出可视区域的内容是否可以滚动。有效值:none(不显示溢出内容)、scroll(滚动显示)。

css 复制代码
@media (overflow-inline: scroll) {}

prefers-contrast

检测用户是否请求系统增加或减少相邻颜色之间的对比度。 在 Media Queries Level 5 中添加。有效值:no-preference(无偏好)、more(增加对比度)、less(减少对比度)、custom(自定义对比度)。

css 复制代码
@media (prefers-contrast: more) {}

prefers-reduced-data

检测用户是否请求了消耗较少 Internet 流量的 Web 内容。有效值:no-preference(无偏好)、reduce(减少数据流量)。

css 复制代码
@media (prefers-reduced-data: no-preference) {}

prefers-reduced-motion

用户喜欢在页面上进行较少的运动。 在 Media Queries Level 5 中添加。有效值:no-preference(无偏好)、reduce(减少运动)。

css 复制代码
@media (prefers-reduced-motion) {}

prefers-reduced-transparency

检测用户是否在其设备上启用了设置,以减少设备上使用的透明或半透明图层效果。有效值:no-preference(无偏好)、reduce(减少透明效果)。

css 复制代码
@media (prefers-reduced-transparency) {}

scan

显示输出是逐行扫描还是隔行扫描。有效值:progressive(逐行扫描)、interlace(隔行扫描)。

css 复制代码
@media screen and (scan: interlace) {}
@media screen and (scan: progressive) {}

scripting

检测脚本(即 JavaScript)是否可用。 在 Media Queries Level 5 中添加。有效值:none(脚本不可用)、initial-only(脚本在初始页面加载期间启用,但之后不会启用)、enabled(脚本可用)。

css 复制代码
@media (scripting: none) {}

@media (scripting: initial-only) {}

@media (scripting: enabled) {}

shape 实验性

检测设备的形状以区分矩形和圆形显示器。有效值:rect(矩形或正方形)、round(圆形或与圆形相似的形状)。

css 复制代码
@media (shape: rect) {}
@media (shape: round) {}

update

输出设备可以修改内容外观的频率。有效值:none(不支持)、slow(慢速)、fast(快速)。

css 复制代码
@media (update: none) {}
@media (update: slow) {}
@media (update: fast) {}

video-dynamic-range

用户代理和输出设备的视频平面支持的亮度、对比度和颜色深度的组合。在 Media Queries Level 5 中添加。有效值:standard(标准)、high(高)。

css 复制代码
@media (video-dynamic-range: high) {}
@media (video-dynamic-range: standard) {}

写在最后

虽然媒体查询多用于响应式布局,但多了解一些其他媒体特性,可做出一些很有用的交互设计效果,比如:深色、浅色主题适配;指针设备、和非指针设备适配等等~~

媒体查询兼容性参考文档:https://developer.mozilla.org/en-US/docs/Web/CSS/@media#browser_compatibility

参考资料:https://developer.mozilla.org/zh-CN/docs/Web/CSS/@media