使用媒体查询
媒体查询(Media queries)允许你根据设备的媒体类型(如打印 vs. 屏幕)或其他特性或特征(如屏幕分辨率或方向、宽高比、浏览器视口的宽度或高度、用户偏好(如希望减少动画、节省流量或启用透明度))来应用 CSS 样式。
媒体查询可用于以下场景:
- 使用 CSS 的
@media和@import@规则来有条件地应用样式。 - 通过
media=或sizes="属性,为<style>、<link>、<source>及其他 HTML 元素指定特定的媒体。 - 使用
Window.matchMedia()和EventTarget.addEventListener()方法测试和监听媒体状态。
备注: 本页面的示例出于演示目的使用了 CSS 的 @media,但所有类型的媒体查询的基本语法都保持不变。
语法
媒体查询由一个可选的媒体类型和任意数量的媒体特性表达式组成,这些表达式可以选择性地通过逻辑运算符以各种方式组合。媒体查询不区分大小写。
-
媒体类型定义了媒体查询所适用的设备的大类:
all、print、screen。除非使用
only逻辑运算符,否则媒体类型是可选的(默认为all)。 -
any-hoverany-pointeraspect-ratiocolorcolor-gamutcolor-indexdevice-aspect-ratio已废弃device-height已废弃device-posturedevice-width已废弃display-modedynamic-rangeforced-colorsgridheighthoverinverted-colorsmonochromeorientationoverflow-blockoverflow-inlinepointerprefers-color-schemeprefers-contrastprefers-reduced-motionprefers-reduced-transparencyresolutionscriptingupdatevideo-dynamic-rangewidth
例如,
hover特性允许查询检查设备是否支持悬停在元素上。媒体特性表达式用于测试其是否存在或其值,并且是完全可选的。每个媒体特性表达式都必须用括号括起来。 -
逻辑运算符可用于构成复杂的媒体查询:
not、and和only。你还可以通过用逗号分隔多个媒体查询,将它们组合成一个规则。
当媒体类型(如果已指定)与文档正在显示的设备匹配,并且所有媒体特性表达式都计算为 true 时,媒体查询的计算结果为 true。涉及未知媒体类型的查询总是为 false。
备注: 即使查询返回 false,附加了媒体查询的 <link> 标签引用的样式表仍然会被下载,下载会发生,但下载的优先级会低很多。不过,除非查询结果变为 true,否则其内容不会被应用。你可以在 Tomayac 的博客文章为什么浏览器会下载媒体查询不匹配的样式表中了解原因。
指定媒体类型
媒体类型描述了给定设备的一般类别。虽然网站通常是为屏幕设计的,但你可能希望创建针对特殊设备(如打印机或基于音频的屏幕阅读器)的样式。例如,此 CSS 针对打印机:
@media print {
/* … */
}
你也可以针对多个设备。例如,这条 @media 规则使用两个媒体查询来同时针对屏幕和打印设备:
@media screen, print {
/* … */
}
请参阅媒体类型以获取可用媒体类型的列表。由于媒体类型以非常宽泛的方式描述设备,最初定义的大多数媒体类型已被废弃,只剩下 screen、print 和 all。要针对更具体的属性,请改用媒体特性。
指定媒体特性
媒体特性描述了给定用户代理、输出设备或环境的特定特征。例如,你可以将特定样式应用于宽屏显示器、使用鼠标的计算机或在低光条件下使用的设备。此示例在用户的主要输入机制(如鼠标)可以悬停在元素上时应用样式:
@media (hover: hover) {
/* … */
}
媒体特性分为范围(range)和离散(discrete)两类。
离散特性的值取自一个枚举的可能关键字值集合。例如,离散特性 orientation 接受 landscape 或 portrait。
@media print and (orientation: portrait) {
/* … */
}
许多范围特性可以加上“min-”或“max-”前缀,以表示“最小条件”或“最大条件”的约束。例如,此 CSS 仅在你的浏览器视口宽度等于或小于 1250px 时应用样式:
@media (max-width: 1250px) {
/* … */
}
以下媒体查询与上面的示例等效:
@media (width <= 1250px) {
/* … */
}
@media (1250px >= width) {
/* … */
}
对于媒体查询的范围特性,你可以使用包含性的 min- 和 max- 前缀,或者更简洁的范围语法运算符 <= 和 >=。
以下媒体查询是等效的:
@media (min-width: 30em) and (max-width: 50em) {
/* … */
}
@media (30em <= width <= 50em) {
/* … */
}
@media (50em >= width >= 30em) {
/* … */
}
上面的范围比较是包含性的。要排除比较值,请使用 < 和/或 >。
@media (30em < width < 50em) {
/* … */
}
@media (50em > width > 30em) {
/* … */
}
如果你创建一个媒体特性查询而没有指定值,那么只要该特性的值不是 0 或 none,嵌套的样式就会被应用。例如,此 CSS 将应用于任何带有彩色屏幕的设备:
@media (color) {
/* … */
}
如果某个特性不适用于浏览器正在运行的设备,那么涉及该媒体特性的表达式总是为 false。
有关更多媒体特性的示例,请参阅每个具体特性的参考页面。
创建复杂的媒体查询
有时你可能想创建一个依赖于多个条件的媒体查询。这时就需要用到逻辑运算符:not、and 和 only。此外,你可以将多个媒体查询组合成一个逗号分隔的列表;这允许你在不同情况下应用相同的样式,其中包含的媒体查询被评估为逻辑上的 or 组合:解释为每个媒体查询都位于括号内,并且它们之间用 or 连接。
在前面的示例中,我们看到了使用 and 运算符将媒体类型与媒体特性分组。and 运算符也可以在单个媒体查询中组合多个媒体特性。not 运算符对媒体查询取反,或者当与括号一起使用时对媒体特性取反,基本上颠倒了它们的正常含义。在某些条件下,or 运算符可用于在单个媒体查询中组合多个媒体特性。最后,only 运算符曾用于防止旧版浏览器在不评估媒体特性表达式的情况下应用样式,但在现代浏览器中没有效果。
备注: 在大多数情况下,当未指定其他类型时,默认使用 all 媒体类型。但是,如果你使用 only 运算符,则必须明确指定媒体类型。你可以看到完整的形式如 only screen 或 only print。
组合多个类型或特性
and 关键字将一个媒体特性与一个媒体类型或其他媒体特性组合起来。此示例组合了两个媒体特性,以将样式限制在宽度至少为 30 ems 的横向设备上:
@media (width >= 30em) and (orientation: landscape) {
/* … */
}
要将样式限制在带屏幕的设备上,你可以将媒体特性链接到 screen 媒体类型:
@media screen and (width >= 30em) and (orientation: landscape) {
/* … */
}
测试多个查询
你可以使用逗号分隔的媒体查询列表,当用户的设备匹配任何一个媒体类型、特性或状态时应用样式。
以下规则包含两个媒体查询。如果用户的设备高度为 680px 或更高,或者浏览器视口处于纵向模式(视口高度大于视口宽度),则该块的样式将应用:
@media (height >= 680px), screen and (orientation: portrait) {
/* … */
}
在此示例中,如果用户正在打印为 PDF 且页面高度为 800px,则媒体查询返回 true,因为第一个查询组件——测试视口高度是否为 680px 或更高——为 true。同样,如果用户在纵向模式的智能手机上,视口高度为 480px,则媒体查询返回 true,因为第二个查询组件为 true。
在逗号分隔的媒体查询列表中,单个媒体查询在逗号处结束,或者对于列表中的最后一个媒体查询,在左大括号({)处结束。
反转查询的含义
not 关键字反转单个媒体查询的含义。例如,此媒体查询中的 CSS 样式将应用于除了打印媒体之外的所有媒体:
@media not print {
/* … */
}
not 仅对其应用的媒体查询取反。不带括号的 not 会对其所在媒体查询中的所有特性取反。这意味着,在逗号分隔的媒体查询列表中,每个 not 都适用于其所在的单个查询,并应用于该单个查询内的所有特性。在此示例中,not 适用于第一个媒体查询 screen and (color),该查询在第一个逗号处结束:
@media not screen and (color), print and (color) {
/* … */
}
由于查询以媒体类型 screen 开头,因此你不能用括号将 screen and (color) 括起来。另一方面,如果你的媒体查询仅由特性组成,则你必须将查询括在括号中:
@media not ((width > 1000px) and (color)), print and (color) {
/* … */
}
括号限制了被取反的查询组件。例如,要仅对 (width > 1000px) 查询取反:
@media (not (width > 1000px)) and (color), print and (color) {
/* … */
}
not 仅对其右侧的查询取反。在此示例中,我们对 hover 媒体特性取反,但不对 screen 媒体类型取反:
@media screen and not (hover) {
/* … */
}
如果设备没有悬停功能,not (hover) 匹配。在这种情况下,由于其顺序,not 适用于 hover 但不适用于 screen。
提高与旧版浏览器的兼容性
only 关键字可防止不支持带媒体特性的媒体查询的旧版浏览器应用给定的样式。它对现代浏览器没有影响。
@media only screen and (color) {
/* … */
}
使用 or 测试多个特性
你可以使用 or 来测试多个特性中是否有一个匹配,如果任何一个特性为 true,则解析为 true。例如,以下查询测试具有单色显示屏或悬停功能的设备:
@media (not (color)) or (hover) {
/* … */
}
请注意,你不能在与 and 和 not 运算符相同的级别上使用 or 运算符。你可以用逗号分隔媒体特性,或者使用括号将媒体特性的子表达式分组,以阐明求值顺序。
例如,以下两个查询都是有效的:
@media ((color) and (hover)) or (monochrome) {
/* … */
}
/* or */
@media (color) and (hover), (monochrome) {
/* … */
}