超越媒体查询:使用新版 HTML 和 CSS 功能进行响应式设计

Avatar of David Atanda
David Atanda 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 $200 免费信用额度!

除了使用媒体查询和现代 CSS 布局(如 flexbox 和 grid)来创建响应式网站之外,我们还可以做一些被忽视的事情来完善响应式网站。在本文中,我们将深入探讨一系列工具(围绕 HTML 和 CSS),从响应式图像到相对较新的 CSS 函数,这些函数无论我们是否使用媒体查询,都自然有效。

事实上,当与这些功能结合使用时,媒体查询更像是补充,而不是完整方法。让我们看看它是如何工作的。

真正响应式的图像

还记得我们以前可以简单地将 width: 100% 添加到图像并称之为结束吗?当然,这仍然有效,并且确实会使图像变得很小,但它也带来了一些缺点,其中最显著的是

  • 图像可能会压缩到失去其焦点。
  • 较小的设备仍然会下载完整的图像。

在 Web 上使用图像时,我们必须确保它们在分辨率和大小方面进行了优化。原因是确保我们拥有适合设备的图像分辨率,这样我们不会为较小的屏幕下载非常大且重的图像,从而最终降低网站的性能。 

简单来说,我们确保将更大的高分辨率图像发送到更大的屏幕,而将较小的低分辨率图像发送到较小的屏幕,从而提高性能和用户体验。

HTML 提供 <picture> 元素,该元素允许我们根据添加的媒体查询指定将要呈现的确切图像资源。如前所述,与其将一个图像(通常是大型高分辨率版本)发送到所有屏幕尺寸并将其缩放至视窗宽度,不如指定一组图像,以便在特定情况下提供服务。

<picture>
  <source media="(max-width:1000px)" srcset="picture-lg.png">
  <source media="(max-width:600px)" srcset="picture-mid.png">
  <source media="(max-width:400px)" srcset="picture-sm.png">
  <img src="picture.png" alt="picture"">
</picture>

在这个例子中,picture.png 是全尺寸图像。从那里,我们定义了图像的下一个最大版本,picture-lg.png,并且尺寸按降序排列,直到最小版本,picture-sm.png。请注意,我们仍然在这个方法中使用媒体查询,但实际上是 <picture> 元素本身驱动着响应式行为,而不是在 CSS 中定义断点。

媒体查询适当地添加,以根据图像的大小进行缩放

  • 视窗大小为 1000 像素及以上的设备会得到 picture.png
  • 视窗大小介于 601 像素和 999 像素之间的设备会得到 picture-lg.png
  • 视窗大小介于 401 像素和 600 像素之间的设备会得到 picture-sm.png
  • 任何小于 400 像素的设备会得到 picture-sm.png

有趣的是,我们还可以通过在 URL 后面使用图像密度(例如 1x、2x、3x 等)来标记每个图像。如果我们制作了彼此成比例的不同图像(我们确实做到了),这将起作用。这使浏览器能够根据屏幕的像素密度以及视窗大小来确定要下载哪个版本。但请注意,我们最终定义了多少个图像

<picture>
  <source media="(max-width:1000px)" srcset="picture-lg_1x.png 1x, picture-lg_2x.png 2x, picture-lg_3x.png 3x">
  <source media="(max-width:600px)" srcset="picture-mid_1x.png 1x, picture-mid_2x.png 2x, picture-mid_3x.png 3x">
  <source media="(max-width:400px)" srcset="picture-small_1x.png 1x, picture-small_2x.png 2x, picture-small_1x.png 3x">
  <img src="picture.png" alt="picture"">
</picture>

让我们具体看看嵌套在 <picture> 元素中的两个标签:<source><img>

浏览器将查找第一个 <source> 元素,其中媒体查询与当前视窗宽度匹配,然后它将显示相应的图像(在 srcset 属性中指定)。<img> 元素作为 <picture> 元素的最后一个子元素是必需的,作为如果初始 source 标签都不匹配的备选方案。

我们还可以使用图像密度来仅使用 <img> 元素和 srcset 属性处理响应式图像

<img
 srcset="
  flower4x.png 4x,
  flower3x.png 3x,
  flower2x.png 2x,
  flower1x.png 1x
 "
 src="flower-fallback.jpg"
>

我们还可以根据 **设备本身** 的 **屏幕分辨率** (通常以每英寸点数或 dpi 衡量),而不是仅仅根据设备视窗,在 CSS 中编写媒体查询。这意味着 **而不是**

@media only screen and (max-width: 600px) {
  /* Style stuff */
}

我们现在拥有

@media only screen and (min-resolution: 192dpi) {
  /* Style stuff */
}

这种方法使我们能够根据设备本身的屏幕分辨率指定要呈现的图像,这在处理高分辨率图像时可能会有所帮助。基本上,这意味着我们可以为支持更高分辨率的屏幕显示高质量图片,而在较低分辨率的屏幕上显示较小版本。值得注意的是,尽管移动设备的屏幕很小,但它们通常具有高分辨率。这意味着仅依靠分辨率来确定要呈现的图像可能不是最好的选择。这可能导致向非常小的屏幕提供大型高分辨率图像,而这可能不是我们真正希望在如此小的屏幕尺寸下显示的版本。

body {
  background-image : picture-md.png; /* the default image */
}


@media only screen and (min-resolution: 192dpi) {
  body {
    background-image : picture-lg.png; /* higher resolution */
  }
}

<picture> 提供的功能本质上是能够对图像进行艺术指导。并且,为了保持这种理念,我们可以利用 CSS 功能,例如 object-fit 属性,它与 object-position 结合使用时,允许我们裁剪图像以获得更好的焦点,同时保持图像的长宽比。

因此,要更改图像的焦点

@media only screen and (min-resolution: 192dpi) {
  body {
    background-image : picture-lg.png;
    object-fit: cover;
    object-position: 100% 150%; /* moves focus toward the middle-right */
  }
}

在 CSS 中设置最小值和最大值

min() 函数指定元素可以缩小的绝对最小尺寸。此函数在帮助文本大小跨不同屏幕尺寸进行适当缩放方面非常有用,例如,从不允许流体类型下降到低于可读字体大小。

html {
  font-size: min(1rem, 22px); /* Stays between 16px and 22px */
}

min() 接受两个值,它们可以是相对值、百分比或固定单位。在这个例子中,我们告诉浏览器永远不要让具有类 .box 的元素的宽度低于 45% 或 600px,以视窗宽度为准,以较小的值为准

.box {
  width : min(45%, 600px)
}

如果 45% 计算出的值小于 600px,则浏览器使用 45% 作为宽度。相反,如果 45% 计算出的值大于 600px,则使用 600px 作为元素的宽度。

max() 函数也是如此。它也接受两个值,但它不是指定元素的最小尺寸,而是定义它可以达到的最大尺寸。

.box {
  width : max(60%, 600px)
}

如果 60% 计算出的值大于 600px,则浏览器使用 60% 作为宽度。另一方面,如果 60% 计算出的值小于 600px,则使用 600px 作为元素的宽度。

钳位值

我们中的许多人一直在呼吁使用 clamp(),并且它实际上已经获得了所有现代浏览器的广泛支持(抱歉,Internet Explorer)。clamp()min()max() 函数的组合,它接受三个参数

  1. 最小值,
  2. 首选值,以及
  3. 最大值

例如

.box {
  font-size : clamp(1rem, 40px, 4rem)
}

浏览器将字体设置为 1rem,直到 1rem 的计算值大于 40px。当计算值超过 40px 时?是的,浏览器在达到 4rem 后将停止增加大小。您可以看到 clamp() 如何用于使元素变得灵活,而无需使用媒体查询。

使用响应式单位

您是否曾经构建过一个带大型标题或副标题的页面,并赞叹它在桌面屏幕上的效果,然后在移动设备上查看它,却发现它太大了?我肯定遇到过这种情况,在本节中,我将解释如何处理此类问题。

在 CSS 中,您可以使用各种测量单位来确定元素的大小或长度,最常用的测量单位包括:pxemrem%vwvh。虽然还有其他一些不常用的单位。我们感兴趣的是,px 可以被认为是绝对单位,而其他单位则被认为是相对单位。

绝对单位

像素 (px) 被认为是绝对单位,主要是因为它是固定的,不会根据其他任何元素的测量值而改变。它可以被认为是其他一些相对单位使用的基础或根单位。尝试将像素用于响应式行为可能会遇到问题,因为它固定不变,但如果您需要元素根本不进行调整大小,则它们非常有用。

相对单位

相对单位,如 %emrem,更适合响应式设计,主要是因为它们能够跨不同屏幕尺寸进行缩放。

vw:相对于视窗宽度
vh:相对于视窗高度
rem:相对于根 (<html>) 元素(默认字体大小通常为 16px)
em:相对于父元素
%:相对于父元素

同样,大多数浏览器默认字体大小为 16px,而 rem 单位使用它来生成计算值。因此,如果用户调整浏览器上的字体大小,页面上的所有内容都将根据根大小进行适当缩放。例如,当处理设置为 16px 的根时,您指定的数字将乘以默认大小。例如

.8rem = 12.8px (.8 * 16)
1rem = 16px (1 * 16)
2rem = 32px (2 * 16)

如果用户或您更改了默认大小会发生什么?正如我们已经说过的,这些是相对单位,最终的大小值将基于新的基本大小。这在媒体查询中非常有用,您只需更改字体大小,整个页面就会相应地放大或缩小。

例如,如果您在 CSS 中将字体大小更改为 10px,则计算后的尺寸最终将为

html {
  font-size : 10px;
}
1rem = 10px (1 * 10)
2rem = 20px (2 * 10)
.5rem = 5px (.5 * 10)

注意:这也适用于百分比 %。例如

100% = 16px;
200% = 32px; 
50% = 8px;

remem 单位之间有什么区别?它取决于单位使用什么作为其基元素。 rem 使用根 (<html>) 元素的字体大小来计算值,而声明 em 值的元素则引用包含它的父元素的字体大小。如果指定父元素的大小与根元素不同(例如,父元素为 18px,但根元素为 16px),则 emrem 将解析为不同的计算值。这使我们能够更精细地控制元素在不同响应式环境中的响应方式。

vh 是“视窗高度”的缩写,即可视屏幕的高度。100vh 代表视窗高度的 100%(取决于设备)。同样,vw 代表“视窗宽度”,表示设备可视屏幕的宽度,而 100vw 实际上代表视窗宽度的 100%。

超越媒体查询

看到没有?我们刚刚浏览了一些非常强大且相对较新的 HTML 和 CSS 功能,这些功能为我们提供了额外的(可能更有效)方法来构建响应式设计。并不是说这些新奇的技术取代了我们一直以来的做法。它们只是我们开发人员工具箱中的更多工具,使我们能够更好地控制元素在不同环境中的行为。无论是处理字体大小、分辨率、宽度、焦点还是其他任何事情,我们对用户体验的控制都比以往更加精细。

因此,下次您在处理一个项目时,希望对特定设备上的设计的外观和感觉有更多控制,请查看原生 HTML 和 CSS 可以提供什么帮助——令人难以置信的是这些技术已经发展到了何种程度。