响应式图像

前端开发

网页上的文本会自动换行到屏幕边缘,以免溢出。而图像则具有固有尺寸。如果图像比屏幕宽,图像就会溢出,用户必须水平滚动才能看到全部内容。

幸运的是,CSS 为您提供了工具来阻止这种情况发生。

限制你的图像

在样式表中,您可以使用max-inline-size 来声明图像的渲染宽度永远不能大于其包含元素的宽度。

img {
  max-inline-size: 100%;
  block-size: auto;
}

注意:如果愿意,您可以使用max-width而不是max-inline-size

您也可以将相同的规则应用于其他类型的嵌入内容,例如视频和 iframe。

img,
video,
iframe {
  max-inline-size: 100%;
  block-size: auto;
}

有了这个规则,浏览器会自动缩小图像以适合屏幕。

响应式图像
限制图像可让用户无需滚动即可看到全部内容

添加一个block-sizeauto意味着浏览器在调整图像大小时会保留图像的纵横比。

有时,图片的尺寸由内容管理系统 (CMS) 或其他内容交付系统设置。如果您的设计需要与 CMS 默认宽高比不同的宽高比,您可以使用以下 aspect-ratio 属性来保留网站的设计:

img {
  max-inline-size: 100%;
  block-size: auto;
  aspect-ratio: 2/1;
}

不幸的是,这通常意味着浏览器必须挤压或拉伸图像以使其适合预期的空间。

改变图像的纵横比会使其看起来被挤压或拉伸
改变图像的纵横比会使其看起来被挤压或拉伸

为了防止挤压和拉伸,请使用该 object-fit属性。

object-fit告诉contain浏览器保留图像的纵横比,并在必要时在图像周围留出空白空间。

img {
  max-inline-size: 100%;
  block-size: auto;
  aspect-ratio: 2/1;
  object-fit: contain;
}

object-fit告诉cover浏览器保留图像的纵横比,并在必要时裁剪图像。

img {
  max-inline-size: 100%;
  block-size: auto;
  aspect-ratio: 2/1;
  object-fit: cover;
}
同一张图片应用了两个不同的“object-fit”值。第一个“object-fit”值为“contain”。第二个“object-fit”值为“cover”
同一张图片应用了两个不同的“object-fit”值。第一个“object-fit”值为“contain”。第二个“object-fit”值为“cover”

您可以使用object-position属性更改图片裁剪的位置 。这会调整裁剪的焦点,这样您就可以确保图片的最重要部分仍然可见

img {
  max-inline-size: 100%;
  block-size: auto;
  aspect-ratio: 2/1;
  object-fit: cover;
  object-position: top center;
}
您可以设置object-position仅裁剪图像的一侧

传递您的图像

这些 CSS 规则会告诉浏览器您希望如何呈现图像。您还可以在 HTML 中提供有关浏览器应如何处理这些图像的提示。

尺寸提示

如果您知道图片的尺寸,请始终包含widthheight 属性。即使由于您的 max-inline-size规则导致图片以不同的尺寸呈现,浏览器仍然知道宽高比,并可以留出适当的空间。这可以防止您的其他内容在图片加载时跳动。

<img
 src="image.png"
 alt="A description of the image."
 width="300"
 height="200"
>

加载提示

使用loading属性来告诉浏览器是否延迟加载图片,直到它位于视口内或附近。对于非首屏图片,请使用 值lazy。浏览器不会加载延迟加载的图片,直到用户向下滚动到图片即将进入视野的程度。如果用户从不滚动,图片就永远不会加载。

<img
 src="image.png"
 alt="A description of the image."
 width="300"
 height="200"
 loading="lazy"
>

对于首屏上方的英雄图像,请勿使用loading。 如果您的网站自动应用该loading="lazy"属性,通常可以将其设置loading为默认值,eager以防止图像被延迟加载:

<img
 src="hero.jpg"
 alt="A description of the image."
 width="1200"
 height="800"
 loading="eager"
>

获取优先级

对于重要的图像(例如LCP图像),您可以通过将属性设置为以下方式,使用“获取优先级”进一步确定加载的优先级:fetchpriorityhigh

<img
 src="hero.jpg"
 alt="A description of the image."
 width="1200"
 height="800"
 loading="eager"
 fetchpriority="high"
>

这会告诉浏览器立即以高优先级获取图像,而不是等到浏览器完成布局并正常获取图像。

但是,当您要求浏览器优先下载某个资源(例如图片)时,浏览器必须降低其他资源(例如脚本或字体文件)的优先级。仅fetchpriority="high"当图片确实至关重要时才设置。

预加载提示

最好尽可能避免预加载,方法是将所有图像都包含在初始 HTML 文件中。但是,某些图像可能不可用,例如通过 JavaScript 添加的图像或 CSS背景图像。

您可以使用预加载让浏览器提前获取这些重要图片。对于真正重要的图片,您可以将此预加载与以下 fetchpriority属性结合使用:

<link rel="preload" href="hero.jpg" as="image" fetchpriority="high">

再次强调,请谨慎使用这些属性,以避免过于频繁地覆盖浏览器的优先级启发式方法。过度使用它们可能会导致性能下降。

一些浏览器支持 基于srcset预加载响应式图像,使用和属性。例如:imagesrcsetimagesizes

<link rel="preload" imagesrcset="hero_sm.jpg 1x hero_med.jpg 2x hero_lg.jpg 3x" as="image" fetchpriority="high">

通过排除href后备,您可以确保不srcset 支持的浏览器仍能预加载正确的图像。

您无法根据浏览器对特定格式的支持情况预加载不同格式的图片。尝试这样做可能会导致额外的下载,从而浪费用户的数据。

图像解码

您还decoding可以向img元素添加一个属性。您可以告诉浏览器该图像可以异步解码,这样它就可以优先处理其他内容。

<img
 src="image.png"
 alt="A description of the image."
 width="300"
 height="200"
 loading="lazy"
 decoding="async"
>

sync如果图像本身是需要优先考虑的最重要的内容,则可以使用该值。

<img
 src="hero.jpg"
 alt="A description of the image."
 width="1200"
 height="800"
 loading="eager"
 decoding="sync"
>

decoding属性不会改变图像解码的速度。它仅影响浏览器是否等待此图像解码完成然后再呈现其他内容。

在大多数情况下,这不会产生太大影响,但有时它可以让浏览器稍微快一点地显示您的图片或其他内容。例如,对于包含大量需要时间渲染的元素的大型文档,以及需要很长时间才能解码的大图片,sync在重要图片上设置会告诉浏览器等待图片并同时渲染两者。或者,您可以设置async让浏览器更快地显示内容,而无需等待图片解码。

然而,更好的选择通常是尽量 避免过大的 DOM 大小 并使用响应式图像来减少解码时间,而不是使用decoding

响应式图像属性srcset

由于该max-inline-size: 100%声明,您的图像不会脱离容器。但是,如果用户的屏幕较小且网络带宽较低,让他们下载与大屏幕用户相同大小的图像会浪费数据。

要解决此问题,请添加同一图像的不同尺寸的多个版本,并使用该srcset 属性告知浏览器这些尺寸的存在以及何时使用它们。

宽度描述符

您可以srcset使用逗号分隔的值列表来定义。每个值都是图像的 URL,后跟一个空格,后跟一些有关图像的元数据(称为描述符)。

在这个例子中,元数据使用w 单位来描述每幅图像的宽度。1w一个像素的宽度。

<img
 src="small-image.png"
 alt="A description of the image."
 width="300"
 height="200"
 loading="lazy"
 decoding="async"
 srcset="small-image.png 300w,
  medium-image.png 600w,
  large-image.png 1200w"
>

该srcset属性是对src属性的补充,而不是替换它。您仍然需要有一个有效的src属性,但浏览器可以使用 中列出的选项之一替换其值srcset。为了节省带宽,浏览器仅在需要时下载较大的图像。

尺寸

如果您使用宽度描述符,您还必须使用该 sizes 属性向浏览器提供更多信息。这会告诉浏览器您期望图像在不同条件下显示的尺寸。这些条件在媒体查询中指定。

sizes属性采用以逗号分隔的媒体查询和图像宽度列表。

注意:在 HTML 元素内使用 CSS 媒体查询感觉很奇怪。它破坏了表示和结构的分离。但这是唯一能够快速提供必要尺寸信息并发挥作用的方法。

<img
 src="small-image.png"
 alt="A description of the image."
 width="300"
 height="200"
 loading="lazy"
 decoding="async"
 srcset="small-image.png 300w,
  medium-image.png 600w,
  large-image.png 1200w"
 sizes="(min-width: 66em) 33vw,
  (min-width: 44em) 50vw,
  100vw"
>

在这个例子中,您告诉浏览器,在宽度超过的视口中 66em,它应该显示不超过屏幕三分之一宽度的图像(例如,在三列布局内)。

44em对于介于和之间的视口宽度66em,将图像显示在屏幕宽度的一半处(如两列布局)。

对于任何比 更窄的尺寸44em,将在屏幕的整个宽度上显示图像。

这意味着最大的图像不一定会用于最宽的屏幕。可以显示多列布局的宽浏览器窗口使用适合一列的图像,该图像可能比用于较窄屏幕上的单列布局的图像更小。

HTML

<main>
  <section>
    <p>This is some introductory text. On a small screen it will be displayed before the image. On a wider screen the image will appear next to this text.</p>
  </section>
  <section>
    <img
     src="https://picsum.photos/seed/picsum/300/300"
     alt="Portrait of a happy-looking handsome dog with a ball in its mouth."
     width="300"
     height="200"
     loading="lazy"
     decoding="async"
     srcset="https://picsum.photos/seed/picsum/300/300 300w,
      https://picsum.photos/seed/picsum/600/300 600w,
      https://picsum.photos/seed/picsum/1200/800 1200w"
     sizes="(min-width: 66em) 33vw,
      (min-width: 44em) 50vw,
      100vw"
    >
  </section>
  <section>
    <p>Here is some more text. On a small screen, this text will appear after the image. Only when the viewport is wide enough will all three pieces of content appear side by side.</p>
  </section>
</main>

CSS

body {
  max-inline-size: 88em;
  padding: var(--metric-box-spacing);
  margin: auto;
}
img {
  max-inline-size: 100%;
  block-size: auto;
  inline-size: 100%;
}
main {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 1em;
}
main section {
  flex-basis: 22em;
  flex-grow: 1;
  padding: var(--metric-box-spacing);
  background-color: var(--color-off-white);
  border-radius: var(--metric-radius);
  box-shadow: var(--generic-shadow);
}

像素密度描述符

您还可以使用描述符来提供在高密度显示器上显示的图像的替代版本,以使图像在其提供的更高分辨率下保持清晰。

像素密度较低的图像看起来可能会模糊
像素密度较低的图像看起来可能会模糊

使用密度描述符来描述图像相对于src属性中图像的像素密度。密度描述符是一个数字,后跟字母 x,如1x2x

<img
 src="small-image.png"
 alt="A description of the image."
 width="300"
 height="200"
 loading="lazy"
 decoding="async"
 srcset="small-image.png 1x,
  medium-image.png 2x,
  large-image.png 3x"
>

如果small-image.png尺寸为 300 x 200 像素,并且medium-image.png 600 x 400 像素,则medium-image.png可以2x在列表中将其放在后面 srcset

您不必使用整数。如果图像的另一个版本大小为 450 x 300 像素,则可以使用 来描述它1.5x

注意:您可以使用宽度描述符或密度描述符,但不能同时使用两者。

展示图像

HTML 中的图像是内容。这就是为什么您alt要为屏幕阅读器和搜索引擎添加带有图像描述的属性。

如果嵌入的图像只是装饰性的,没有任何有意义的内容,则可以使用空alt属性。

<img
 src="flourish.png"
 alt=""
 width="400"
 height="50"
>

必须始终包含alt属性,即使它是空的。空alt属性会告诉屏幕阅读器该图像是展示性的。缺少alt属性不会提供该信息。

理想情况下,展示性或装饰性图像应包含在 CSS 中,而不是 HTML 中。HTML 用于结构。CSS 用于展示。

背景图像

使用CSS 中的background-image属性来加载演示图像。

element {
  background-image: url(flourish.png);
}

image-set 您可以使用函数指定多个图像候选项 background-image

CSS 中的函数与 HTML 中的属性image-set非常相似srcset。提供一个图像列表,其中包含每个图像的像素密度描述符。

element {
  background-image: image-set(
    small-image.png 1x,
    medium-image.png 2x,
    large-image.png 3x
  );
}

浏览器根据设备的像素密度选择最合适的图像。

向网站添加图像时需要考虑许多因素,包括:

  • 为每个图像保留适当的空间。
  • 确定您需要多少种尺寸。
  • 确定图像是内容还是装饰。
  • 花时间让图片变得完美是值得的。糟糕的图片策略会让您的用户感到烦恼和沮丧。良好的图片策略会让您的网站看起来简洁明了,无论用户使用什么设备或网络连接。

您的工具包中还有一个 HTML 元素可让您更好地控制图像:元素picture

内容来自WEB.DEV:https://web.dev/learn/design/responsive-images

Post Comment