新的 CSS 媒体查询范围语法

Avatar of Preethi Selvam
Preethi Selvam

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200 美元的免费积分!

我们依赖于 CSS 媒体查询 来根据目标条件选择和设置元素的样式。 该条件可以是各种各样的东西,但通常分为两类:(1)正在使用的媒体类型,以及(2)浏览器、设备甚至用户环境的特定功能。

因此,假设我们要对打印文档应用某些 CSS 样式

@media print {
  .element {
    /* Style away! */
  }
}

我们可以根据特定视窗宽度应用样式,这一事实使 CSS 媒体查询成为响应式网页设计的核心要素,自 Ethan Marcotte 创造了这个词 以来。 如果浏览器的视窗宽度为特定大小,则应用一组样式规则,这使我们能够设计响应于浏览器大小的元素。

/* When the viewport width is at least 30em... */
@media screen and (min-width: 30em) {
  .element {
    /* Style away! */
  }
}

注意其中的 and 吗? 这是一个运算符,允许我们组合语句。 在该示例中,我们将媒体类型为 screenmin-width 特性设置为 30em(或更高)的条件组合在一起。 我们可以做同样的事情来定位视窗大小范围

/* When the viewport width is between 30em - 80em */
@media screen and (min-width: 30em) and (max-width: 80em) {
  .element {
    /* Style away! */
  }
}

现在,这些样式适用于显式的视窗宽度范围,而不是单个宽度!

但媒体查询级别 4 规范引入了一种新的语法,用于使用常见的数学比较运算符来定位视窗宽度的范围——例如 <>=——在编写代码时,这些运算符在语法上更有意义,同时代码更少。

让我们深入了解它的工作原理。

新的比较运算符

最后一个例子很好地说明了我们如何通过使用 and 运算符组合条件来“伪造”范围。 媒体查询级别 4 规范中的重大变化是,我们有了新的运算符来比较值,而不是组合它们

  • < 评估一个值是否小于另一个值
  • > 评估一个值是否大于另一个值
  • = 评估一个值是否等于另一个值
  • <= 评估一个值是否小于或等于另一个值
  • >= 评估一个值是否大于或等于另一个值

以下是我们如何编写一个媒体查询,如果浏览器宽度为 600px 或更大,则应用样式

@media (min-width: 600px) {
  .element {
    /* Style away! */
  }
}

以下是使用比较运算符编写相同内容的方式

@media (width >= 600px) {
  .element {
    /* Style away! */
  }
}

定位视窗宽度范围

通常,当我们编写 CSS 媒体查询时,我们创建的是所谓的 断点——设计“中断”并应用一组样式来修复它的条件。 设计可以有多个断点! 它们通常基于视窗介于两个宽度之间:断点开始的位置和断点结束的位置。

以下是我们如何使用 and 运算符组合两个断点值来实现这一点

/* When the browser is between 400px - 1000px */
@media (min-width: 400px) and (max-width: 1000px) {
  /* etc. */
}

您开始了解到,当我们放弃布尔 and 运算符而采用新的范围比较语法时,编写媒体查询要短得多、更容易。

@media (400px <= width <= 1000px) {
  /* etc. */
}

容易多了,对吧? 而且它清楚地说明了这个媒体查询在做什么。

浏览器支持

截至本文撰写之时,这种改进的媒体查询语法还处于早期阶段,目前还没有像结合 min-widthmax-width 的方法那样得到广泛支持。 不过,我们正在接近! 截至目前,Safari 是唯一一个主要的坚持者,但 有一个关于它的公开票据,您可以关注它。

这些浏览器支持数据来自 Caniuse,它提供了更多详细信息。 数字表示浏览器从该版本开始支持该功能。

桌面

ChromeFirefoxIEEdgeSafari
1046310416.4

移动/平板电脑

Android ChromeAndroid FirefoxAndroidiOS Safari
12712712716.4

让我们看一个例子

这是一个适合更大屏幕(如台式机)的布局

A desktop layout with a logo and menu up top, a large heading in white, and an image of a silhouetted person underneath the heading, followed by a footer.

此布局具有所有断点通用的基本样式。 但随着屏幕变窄,我们开始应用条件应用于不同较小断点的样式,这些样式非常适合平板电脑,一直到手机

Side-by-side screenshots of the mobile and tablet layouts with their CSS Grid tracks overlaid.

要查看正在发生的事情,以下是布局在两个较小断点之间如何响应。 隐藏的导航列表显示出来,以及 main 中的 titlefont-size 增加了。

当视窗的更改从匹配一个媒体的条件变为另一个媒体的条件时,就会触发该更改

/* Base styles (any screen size) */
header {
  display: flex;
  justify-content: center;
}

header ul {
  display: none;
}

.title p {
  font-size: 3.75rem;
}

/* When the media type is a screen with a width greater or equal to 768px */
@media screen and (width >= 768px) {
  header {
    justify-content: space-between;
  }

  header ul {
    display: flex;
    justify-content: space-between;
    gap: 3rem;
  }

  .title p {
    font-size: 5.75rem;
  }
}

我们结合了一些我们已经讨论过的概念! 我们定位具有 screen 媒体类型的设备,使用新的媒体特性范围语法评估视窗宽度是否大于或等于特定值,并使用 and 运算符组合这两个条件。

Diagram of the media query syntax, detailing the media type, operator, and range media feature.

好的,这对 768px 以下的移动设备以及等于或大于 768px 的其他设备来说很棒。 但是,桌面布局怎么办……我们如何才能做到这一点?

就布局而言

  • main 元素变为 12 列网格。
  • 在图像上显示一个按钮。
  • .title 元素的字体大小增加并与图像重叠。

假设我们已经完成了功课并确定了这些更改的确切发生位置,我们可以在视窗匹配该断点的 width 条件时应用这些样式。 我们将说断点在 1000px

/* When the media type is a screen with a width greater or equal to 1000px  */
@media screen and (width >= 1000px) {
  /* Becomes a 12-column grid */
  main {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    grid-template-rows: auto 250px;
  }

  /* Places the .title on the grid */
  .title {
    grid-row: 1;
  }

  /* Bumps up the font-size */
  .title p {
    font-size: 7.75rem;
  }

  /* Places .images on the grid */
  .images {
    grid-row: 1 / span 2;
    align-self: end;
    position: relative;
  }

  /* Displays the button */
  .images .button {
    display: block;
    position: absolute;
    inset-block-end: 5rem;
    inset-inline-end: -1rem;
  }
}
Showing the CSS grid tracks for a desktop layout using a CSS media query with the new range syntax.

试玩一下

为什么新的语法更容易理解

底线:区分比较运算符(例如 width >= 320px)比使用 and 运算符区分 min-widthmax-width 容易。 通过消除 min-max- 之间的细微差别,我们只有一个 width 参数可以使用,运算符告诉我们其他信息。

除了这些语法的视觉差异之外,它们还在做一些细微的不同的事情。 使用 min-max- 等效于使用数学比较运算符

  • max-width 等效于 <= 运算符(例如 (max-width: 320px) 等效于 (width <= 320px))。
  • min-width 等效于 >= 运算符(例如 (min-width: 320px) 等效于 (width >= 320px))。

请注意,两者都不等效于 >< 运算符。

让我们直接从媒体查询级别 4 规范中提取一个示例,其中我们使用 min-widthmax-width 根据视窗宽度在 320px 处的断点定义不同的样式

@media (max-width: 320px) { /* styles for viewports <= 320px */ }
@media (min-width: 320px) { /* styles for viewports >= 320px */ }

当视窗宽度等于 320px 时,两个媒体查询都会匹配条件。 这并不完全是我们想要的。 我们想要其中一个条件,而不是同时满足两个条件。 为了避免这种隐式更改,我们可以根据 min-width 在查询中添加一个像素

@media (max-width: 320px){ /* styles for viewports <= 320px */ }
@media (min-width: 321px){ /* styles for viewports >= 321px */ }

虽然这确保了当视窗宽度为 320px 时,两组样式不会同时应用,但任何介于 320px321px 之间的视窗宽度将导致一个非常小的区域,其中两个查询中的样式都不会应用——这是一种奇怪的“无样式内容闪烁”情况。

一种解决方案是将第二个比较标度值(小数点后的数字)增加到 320.01px

@media (max-width: 320px) { /* styles for viewports <= 320px */ }
@media (min-width: 320.01px) { /* styles for viewports >= 320.01px */ }

但这变得很愚蠢且过于复杂。 这就是新的媒体特性范围语法是更合适的方法的原因

@media (width <= 320px) { /* styles for viewports <= 320px */ }
@media (width > 320px) { /* styles for viewports > 320px */ }

总结

Whew,我们已经涵盖了 CSS 媒体查询中针对视窗宽度范围的新语法。现在 Media Queries Level 4 规范已经引入了该语法,并且已被 Firefox 和 Chromium 浏览器采用,我们正在接近能够使用新的比较运算符并将其与除 `width` 之外的其他范围媒体特征(如 `height` 和 `aspect-ratio`)结合使用。

这只是 Level 4 规范引入的新功能之一,与之一起的还有 我们可以根据用户偏好进行的一系列查询。但这才仅仅是开始!查看 CSS 媒体查询完整指南,抢先了解 Media Queries Level 5 可能包含的内容