CSS aspect-ratio 属性

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

宽高比

Browser Support

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

Source

宽高比最常以两个整数和一个冒号表示,格式为:宽度:高度,或 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 演示可视化图表
展示各种 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 的宽高比。

为了提高这些图片的响应速度,我们可以使用宽高比。这样一来,我们就可以设置特定的宽高比,并根据单个轴(高度或宽度)调整其余媒体的大小。

目前,一种基于图片宽度来保持宽高比的跨浏览器解决方案被广泛接受,称为“Padding-Top 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 保持宽高比

使用宽高比在轮播界面中为帖子预览图片设置 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 上查看演示。

奖励提示:宽高比的图片属性

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

对于上面的示例,假设图片尺寸为 800x600 像素,则图片标记如下所示:<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 提供。