CSS aspect-ratio 属性

此 CSS 属性有助于在自适应布局中保持间距。

宽高比

浏览器支持

  • Chrome:88。
  • Edge:88.
  • Firefox:89。
  • Safari:15.

来源

纵横比最常以两个整数和一个英文冒号的形式表示,即宽度:高度或 x:y。最常见的摄影宽高比为 4:3 和 3:2,而视频和较新款的消费类相机的宽高比往往为 16:9。

两张宽高比相同的图片。一个是 634 x 951 像素,另一个是 200 x 300 像素。两者的宽高比均为 2:3。
两张宽高比相同的图片。一个是 634 x 951 像素,另一个是 200 x 300 像素。两者的宽高比均为 2:3。

随着响应式设计的出现,保持宽高比对 Web 开发者来说变得越来越重要,尤其是在图片尺寸不同且元素大小会根据可用空间而变化的情况下。

以下是一些需要保持宽高比的重要场景示例:

  • 创建自适应 iframe,其宽度为父级宽度的 100%,高度应保持特定的视口宽高比
  • 为图片、视频和嵌入内容创建内在占位符容器,以防止在这些内容加载并占用空间时重新布局
  • 为交互式数据可视化或 SVG 动画创建统一的自适应空间
  • 为卡片或日历日期等多元素组件创建统一的自适应空间
  • 为尺寸各异的多个图片创建统一的自适应空间(可与 object-fit 搭配使用)

object-fit

定义宽高比有助于我们在自适应环境中调整媒体大小。此分桶中的另一个工具是 object-fit 属性,可让用户描述某个分块中的对象(例如图片)应如何填充该分块:

对象适应演示可视化
展示各种 object-fit 值。请参阅 Codepen 上的演示

initialfill 值会重新调整图片以填充空间。在我们的示例中,由于系统会重新调整像素,因此会导致图片变形和模糊。不理想。object-fit: cover 会使用图片的最小尺寸来填充空间,并根据此尺寸剪裁图片以使其适合该空间。它会在其最小边界处“放大”。object-fit: contain 可确保整个图片始终可见,与 cover 相反,后者会采用最大的边界大小(在上面的示例中,这是宽度),并调整图片大小,以便在保持其固有宽高比的同时适应空间。object-fit: none 示例显示了在中心(默认对象位置)以自然尺寸剪裁的图片。

在大多数情况下,object-fit: cover 往往可在处理不同尺寸的图片时确保实现良好的统一界面,但这样会丢失信息(图片会在最长边被剪裁)。

如果这些细节很重要(例如,在处理美妆产品的平铺照片时),则不得剪裁重要内容。因此,理想情况下,自适应图片应具有不同的尺寸,能够适应界面空间,而无需剪裁。

老技巧:使用 padding-top 保持宽高比

使用 padding-top 为轮播界面中的帖子预览图片设置 1:1 的宽高比。
使用 padding-top 为轮播界面中的帖子预览图片设置 1:1 的宽高比。

为了让这些元素更具响应能力,我们可以使用宽高比。这样,我们就可以设置特定的宽高比尺寸,并将媒体的其余部分基于单个轴(高度或宽度)。

为了根据图片宽度保持宽高比,目前广接受的跨浏览器解决方案被称为“上内边距 Hack”。此解决方案需要一个父容器和一个绝对放置的子容器。然后,将宽高比计算为百分比,以设置为 padding-top。例如:

  • 宽高比为 1:1 = 1 / 1 = 1 = padding-top: 100%
  • 4:3 宽高比 = 3 / 4 = 0.75 = padding-top: 75%
  • 宽高比 3:2 = 2 / 3 = 0.66666 = padding-top: 66.67%
  • 宽高比 16:9 = 9/16 = 0.5625 = padding-top: 56.25%

确定宽高比值后,我们可以将其应用于父级容器。请参考以下示例:

<div class="container">
  <img class="media" src="..." alt="...">
</div>

然后,我们可以编写以下 CSS:

.container {
  position: relative;
  width: 100%;
  padding-top: 56.25%; /* 16:9 Aspect Ratio */
}

.media {
  position: absolute;
  top: 0;
}

使用 aspect-ratio 保持宽高比

使用 aspect-ratio 为轮播界面中的帖子预览图片设置 1:1 的宽高比。
使用 aspect-ratio 为轮播界面中的帖子预览图片设置 1:1 的宽高比。

遗憾的是,计算这些 padding-top 值并不直观,并且需要一些额外的开销和定位。借助新的固有 aspect-ratio CSS 属性,保持宽高比所用的语言更清晰。

使用相同的标记,我们可以将 padding-top: 56.25% 替换为 aspect-ratio: 16 / 9,并将 aspect-ratio 设置为指定的 width / height 比率。

使用 padding-top
.container {
  width: 100%;
  padding-top: 56.25%;
}
使用 aspect-ratio
.container {
  width: 100%;
  aspect-ratio: 16 / 9;
}

使用 aspect-ratio 代替 padding-top 会更加清晰明了,而且不会更新内边距属性来执行超出其常规范围的操作。

此新属性还添加了向 auto 设置宽高比的功能,其中“具有内在宽高比的替换元素会使用该宽高比;否则,该框没有首选宽高比。”如果同时指定了 auto<ratio>,则首选宽高比为 width 除以 height 的指定宽高比,除非它是具有固有宽高比的被替换元素,在这种情况下会改用宽高比。

示例:网格中的一致性

这也非常适用于 CSS 网格和 Flexbox 等 CSS 布局机制。假设您有一个列表,其中包含您希望保持 1:1 宽高比的子项,例如赞助商图标网格:

<ul class="sponsor-grid">
  <li class="sponsor">
    <img src="..." alt="..."/>
  </li>
  <li class="sponsor">
    <img src="..." alt="..."/>
  </li>
</ul>
.sponsor-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
}

.sponsor img {
  aspect-ratio: 1 / 1;
  width: 100%;
  object-fit: contain;
}
网格中的图片及其父元素,采用不同的宽高比尺寸。在 Codepen 上查看演示

示例:防止布局偏移

aspect-ratio 的另一项出色功能是,它可以创建占位符空间,以防止累积布局偏移并提供更好的Web Vitals。在第一个示例中,从 Unsplash 等 API 加载资源会在媒体加载完毕时导致布局偏移。

视频:在已加载的素材资源未设置宽高比时发生的累计布局偏移。此视频是使用模拟的 3G 网络录制的。

另一方面,使用 aspect-ratio 会创建一个占位符来防止这种布局偏移:

img {
  width: 100%;
  aspect-ratio: 8 / 6;
}
在已加载的资产上设置了宽高比设定的视频。此视频是使用模拟的 3G 网络录制的。在 Codepen 上查看演示

额外提示:宽高比的图片属性

设置图片宽高比的另一种方法是通过 image 属性。如果您事先知道图片的尺寸,那么最佳实践是将这些尺寸设置为其 widthheight

在上述示例中,我们知道尺寸为 800 x 600 像素,因此图片标记将如下所示:<img src="image.jpg" alt="..." width="800" height="600">。如果发送的图片具有相同的宽高比,但不一定具有这些确切的像素值,我们仍然可以使用图片属性值设置宽高比,并结合使用 width: 100% 样式,以便图片占据适当的空间。所有这些代码加起来将如下所示:

<!-- Markup -->
<img src="image.jpg" alt="..." width="8" height="6">
/* CSS */
img {
  width: 100%;
  height: auto;
}

最终,其效果与通过 CSS 在图片上设置 aspect-ratio 相同,并且可以避免累积布局偏移(请参阅 Codepen 上的演示)。

总结

借助新的 aspect-ratio CSS 属性,您可以更轻松地在多个现代浏览器中发布应用,并在媒体和布局容器中保持适当的宽高比。

照片由 Amy ShamblenLionel Gustave 提供,来自 Unsplash。