在 CSS 中使用图像集来使用高性能的下一代图像

Avatar of Ollie Williams
Ollie Williams

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

CSS image-set() 函数自 2012 年以来一直得到基于 Chromium 的浏览器的支持,并在 Safari 版本 6 以来得到支持。 支持最近在 Firefox 88 中实现。 让我们深入研究,看看我们今天可以使用 image-set() 做些什么,以及不能做些什么。

同一图像的多重分辨率

以下是对 image-set()CSS 规范 的描述。

为用户的设备提供最合适的图像分辨率可能是一项艰巨的任务。 理想情况下,图像应与查看它们的设备分辨率相同,这在用户之间可能会有所不同。 但是,其他因素可能会影响决定使用哪个图像; 例如,如果用户处于缓慢的移动网络连接中,他们可能更喜欢接收低分辨率图像,而不是等待加载大型高分辨率图像。

它基本上是 CSS 背景,等同于用于 img 标签的 HTML srcset 属性。 通过使用 image-set,我们可以提供图像的多重分辨率,并相信浏览器会做出最佳决策以决定使用哪一个。 这可用于为三种不同的 CSS 属性指定值:contentcursor,最有用的是 background-image

.hero {
  background-image: image-set("platypus.png" 1x, "platypus-2x.png" 2x);
}

1x 用于标识低分辨率图像,而 2x 用于定义高分辨率图像。 xdppx 的别名,代表 **每像素点单位**。

Chrome/Edge/Opera/Samsung Internet 目前需要 -webkit- 前缀。 如果您使用的是 Autoprefixer,这将自动处理。 Safari 不再需要前缀,但使用旧语法,该语法要求使用 url() 函数来指定图像路径。 我们也可以包含一个普通的 background-image: url() 来支持任何不支持 image-set 的浏览器。

.hero {
  /* Fallback */
  background-image: url("platypus.png");

  /* Chrome/Edge/Opera/Samsung, Safari will fallback to this as well */
  background-image: -webkit-image-set(url("platypus.png") 1x, url("platypus-2x.png") 2x);

  /* Standard use */
  background-image: image-set("platypus.png" 1x, "platypus-2x.png" 2x);
}

现在,使用昂贵的高端设备的用户将看到超级清晰的图像。 对于慢速连接或使用廉价屏幕的用户,性能将得到提升,因为他们的浏览器将自动请求低分辨率图像。 如果您想确保在高分辨率设备上甚至在慢速连接上也使用高分辨率图像,可以使用 min-resolution 媒体查询而不是 image-set。 有关为高密度屏幕提供清晰图像的更多信息,请查看 Jake Archibald 最近发布的 博客文章

这很酷,但我真正想要的是能够在 CSS 中采用最新的图像格式,同时仍然满足旧浏览器的需求……

新的图像格式

Safari 14 发布了对 WebP 的支持。 它是最后一个支持该图像格式的现代浏览器,这意味着该图像格式现在得到了所有浏览器的支持(Internet Explorer 除外)。 WebP 的优点是可以生成通常比 JPG、PNG 或 GIF 更小(但质量相同的)图像。

还出现了一堆更新的图像格式。 AVIF 图像 的尺寸惊人地小。 Chrome、Opera 和 Samsung Internet 已经发布了对 AVIF 的支持。 它已经在 Firefox 中处于旗帜状态。 这种图像格式尚未得到许多设计工具的支持,但您可以使用 Google Chrome 团队构建的 Squoosh 应用程序 将图像转换为 AVIF。 WebP 2、HEIF 和 JPEG XL 最终也可能会进入浏览器。 所有这些都非常令人兴奋,但我们希望不支持这些更新格式的浏览器也能获取一些图像。 幸运的是,image-set() 有一个为此提供的语法。

通过指定类型来使用新的图像格式

浏览器支持说明: 我将要讨论的 image-set 的功能目前在浏览器中支持得非常糟糕。 目前仅在 Firefox 89 中得到支持。

HTML 已经多年来支持 <picture> 元素。

<picture>
  <source srcset="./kitten.avif" type="image/avif">
  <img src="./kitten.jpg" alt="a small kitten"> 
</picture>

image-set 提供了 CSS 等效项,允许通过指定图像的 MIME 类型来使用下一代图像格式。

.div1 {
  background-image: image-set(
    "kitten.avif" type("image/avif"),
    "kitten.jpg" type("image/jpeg")
  );
}

下一代图像排在第一位,而旧浏览器的回退图像排在第二位。 仅下载一个图像。 如果浏览器不支持 AVIF,它将忽略它,并且仅下载您指定的第二个图像。 如果支持 AVIF,则会忽略回退图像。

在上面的示例中,我们使用了一个 AVIF 图像,并提供了一个 JPEG 作为回退,但回退可以是任何广泛支持的图像格式。 以下是如何使用 PNG 的示例。

.div2 {
  background-image: image-set(
    "puppy.webp" type("image/webp"),
    "puppy.png" type("image/png")
  );
}

在 Chromium 和 Safari 中,目前不支持指定 type。 这意味着您今天只能使用 image-set 来指定广泛支持的图像格式的不同分辨率,而不能在这些浏览器中使用 WebP 或 AVIF 时添加向后兼容性。 如果您有这种倾向,应该可以同时提供多重分辨率和多重图像格式。

.div2 {
  background-image: image-set( 
    "puppy.webp" type("image/webp") 1x,
    "puppy2x.webp" type("image/webp") 2x,
    "puppy.png" type("image/png") 1x,
    "puppy2x.png" type("image/png") 2x
  );
}

希望浏览器支持很快会得到改进。

改用 <picture> 来显示背景

也许您根本不需要 background-image。 如果您想使用现代图像格式,您可以使用 <picture> 元素,它在浏览器中的支持度更高。 如果将图像设置为 position: absolute,则可以轻松地在其上显示其他元素。

作为使用 position: absolute 的替代方法,CSS 网格是另一种轻松叠加 HTML 元素的方法。