可变比例布局中的流体图像

Avatar of Lari Maza
Lari Maza

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

如今,当图像单独出现在布局中时,创建流体图像非常容易。但是,随着更复杂的界面出现,我们经常需要将图像放置在响应式元素内部,例如这张卡片

Screenshot. A horizontal card element with an image of two strawberries against a light blue background to the left of text that contains a heading and two sentences.

现在,假设这张图像不是语义内容,而只是装饰。这是使用 `background-image` 的一个很好的用途。由于在此上下文中,图像包含一个对象,我们不能在响应式情况下允许任何部分被裁剪,因此我们将选择 `background-size: contain`。

这里开始变得棘手:在移动设备上,这张卡片会改变方向并变成垂直的,图像在顶部。我们可以使用任何类型的 CSS 布局技术实现这一点,并且可能最好使用 CSS 网格或 flexbox 处理。

Screenshot. The same strawberry card but in a vertical format.

但是,当我们测试更小的屏幕时,由于 `background-size: contain` 属性,我们会得到以下结果

The same card element in vertical but now the strawberry image is not flush with the top border of the card.
嘿,回到上面去!

这不太好。图像会调整大小以保持其纵横比,不会切断任何细节,如果图像非常重要的内容并且不应该被裁剪,我们就不能将 `background-size` 更改为 `cover`。

此时,我们可能会想到下一个尝试:将图像内联放置,而不是背景。

在桌面版上,这工作正常

在移动版上也不错

但在更小的屏幕上,由于所有固定大小,图像的比例会失真。

Screenshot. The vertical card element with the strawberry image out of proportion, causing the strawberries to appear stretched vertically.
嗯,这些草莓被拉伸后就没有那么可口了。

我们可以花几个小时调整图像、卡片、flex 属性,来回调整。或者,我们可以……

将主要内容与背景分离

这是在响应式图像方面获得更多灵活性和弹性的基础。这可能并非始终可以实现,但在很多情况下,可以通过在设计方面稍微努力来实现,特别是如果事先计划了这种方法。

在我们的下一个迭代中,我们将草莓图像放置在透明背景上,并使用 CSS 设置光栅图像中的蓝色。通过调整示例空间的大小,继续在演示中玩转视窗大小!

更深入地观察样式,请注意,我们还为包含图像的 div 添加了填充,因此草莓不会太靠近边缘。我们可以通过这种填充完全控制草莓与边缘之间的距离。

请注意,我们还使用负边距来弥补外部卡片包装上的填充,否则图像周围会出现空白。

对内联图像使用 `object-fit` 属性

尽管之前的演示有效,但我们仍然可以改进这种方法。到目前为止,我们假设图像是非语义内容——但通过这种布局,图像插图也很可能不仅仅是装饰。

如果是这样,我们绝对不希望图像被裁剪掉,因为这将相当于数据丢失。将图像内联放置而不是背景,在语义上更好,可以防止这种情况,我们可以使用 `object-fit` 属性来实现这一点。

我们将草莓从背景中提取出来,现在它是一个内联 `<img>` 元素,但我们保留了该图像 div 中的相同背景颜色。

最后,将 `object-fit: contain` 与 100% 的宽度结合起来,可以调整窗口大小并保持草莓的纵横比。然而,这种方法的缺点是我们需要为桌面版本上的图像设置一个固定高度——否则它将遵循设置宽度的比例(缩小它将改变布局)。如果我们需要生成带有可变文本量的卡片,这些文本会换行,这可能会让布局过于受限。

即将推出:`aspect-ratio`

针对上述问题的解决方案可能即将推出,使用即将推出的 `aspect-ratio` 属性。这将使我们能够为元素设置一个固定比率,例如

.el {
  aspect-ratio: 16 / 9;
}

这意味着我们可以消除固定高度并用计算出的纵横比替换它。例如,最后一个示例的桌面断点中的尺寸如下所示

.image {
  /* ... */
  height: 184px;
  width: 318px;
}

使用 `aspect-ratio`,我们可以删除高度声明并进行计算以获得最接近 184 的比率

.image {
  /* ... */
  width: 318px; /*  Base width */
  height: unset; /* Resets the height that was set outside the media query */
  aspect-ratio: 159 / 92; /* Amounts close to a 184px height */
}

如果您想了解更多信息,可以在 这篇文章 中进一步了解这个即将推出的属性。

最后,在可变比例布局中,有多种方法可以实现可靠的响应式图像。但是,使这项工作变得更轻松、更好的技巧并不一定在于 CSS;它可能很简单,只需调整图像即可,无论是在分离前景和背景(如我们所做的那样),还是选择即使边缘被裁剪掉很大一部分也能正常工作的特定图像。