【问题标题】:How set width and height attributes for <img> element within <picture> element to prevent layout shifts?如何为 <picture> 元素中的 <img> 元素设置宽度和高度属性以防止布局偏移?
【发布时间】:2021-03-02 01:30:14
【问题描述】:

在 Chrome DevTools 中运行 Lighthouse,它说 CLS(累积布局转换)需要改进。

我知道现代浏览器现在根据图像的widthheight 属性设置图像的默认纵横比。因此,最佳做法是应设置widthheight 属性以防止布局变化。

尽管如此,我还是省略了设置 widthheight 属性,因为这是我让它按照我想要的方式工作的唯一方法(请参阅下面的代码)。

因为我有 WebP 格式的图像(带有 png 后备),我不得不使用 &lt;picture&gt; 元素(以便不支持 WebP 的浏览器获得图像的 png 版本)。请注意,我使用的是相同图像的不同尺寸版本。

因此,如果我没有使用 WebP 格式,我会单独使用 &lt;img&gt; 而不是 &lt;picture&gt;。多亏了纵横比,问题就会得到解决。

正如您在下面的代码 sn-p 中看到的,在这个特定示例中,同一张图片有两个版本。在&lt;img&gt; 中设置width="245"height="600" 会导致我的两个不同尺寸版本的相同图像 的最大尺寸为245 x 600px(它当然会根据具有较小的视口)。根据我的媒体查询,对于更宽的视口(最小宽度:813px),我提供相同图像的较大版本,但在&lt;img&gt; 中设置widthheight,图像会缩小到 245 x 600 像素。

现在回答我的问题;如果可能的话,我可以做些什么来为我的&lt;img&gt; 元素在我的&lt;picture&gt; 元素中设置widthheight 属性以防止布局变化(并且这样做还可以获得其他好处,例如更快的加载次)?因此,如何让浏览器利用纵横比以正确的方式显示我的图像?

我非常感谢有人对此提供指导。

谢谢/卡尔

<picture>
            <source 
              media="(max-width: 812px)" 
              srcset="image-245w.webp"
              type="image/webp"
            >
            <source 
              media="(min-width: 813px)" 
              srcset="image-332w.webp"
              type="image/webp"
            >
            <source 
              media="(max-width: 812px)" 
              srcset="image-245w.png"
              type="image/png"
            >
            <source 
              media="(min-width: 813px)" 
              srcset="image-332w.png"
              type="image/png"
            >
            <img class="img-fluid" src="image-245w.png" alt="image">     
</picture>

【问题讨论】:

  • 好吧,从技术上讲,您没有应用高度或宽度。这个 sn-p 中没有包含高度或宽度的 css。在编辑之前,您拥有属性:width="600",这在技术上是行不通的。 600什么?宽度 = 600 根香蕉?西红柿?...您还需要命名一个单元,例如px, vw/vh, em, % ...
  • 您好,是的,我在文本中省略了 px。实际上,您没有在属性“宽度”和“高度”中指定任何内容。正确的是 width="245" height="600" 没有 px、em 或任何东西。
  • 我发现,在 HTML 规范中为 &lt;source&gt; 定义了 widthheighthtml.spec.whatwg.org/multipage/…。在 &lt;picture&gt; 元素内使用时。但是我没有测试如果没有 CLS 是否可以工作

标签: html css


【解决方案1】:

我做了一些测试,得出的结论是,在图像元素上使用widthheight(你应该这样做)会取消sizes 属性。如果您设置了widthheight,您将无法让您的响应式图像正常工作。

我创建了一个显示不同组合的小型仓库:https://www.gijsvandam.nl/responsive-picture-element/

解决方案是使用sizes如果你使用widthheight,而是依赖css来设置正确的宽度和高度.

<picture>
            <source 
              srcset="image-245w.webp 245w, image-332w.webp 332w"
              type="image/webp"
            >
            <img
              srcset="image-245w.png 245w, image-332w.png 332w" 
              class="img-fluid" 
              src="image-245w.png" 
              alt="image" 
              width="245" 
              height="600">     
</picture>
     @media (max-width: 812px) {
        .img-fluid {
           width: 245px;
           height: auto;
        }
      }
      @media (min-width: 813px) {
        .img-fluid {
           width: 332px;
           height: auto;
        }
      }

重要的是要了解srcSetsizes 组合(或与上述css 组合)并不一定会强制浏览器使用一个图像或另一个图像。根据device pixel ratio,浏览器可能会选择加载更大的图像以显示在 245 像素宽的图像槽中。您只需要相信浏览器会为工作选择最佳文件。 “大小”和srcSet 之间没有一对一的关系。这就是为什么您可以在srcSet 中提供比sizes 属性中的选项更多(或更少)的文件。

【讨论】:

  • 但是,如果您删除“尺寸”,浏览器如何选择最合适的图像? “sizes”不是告诉浏览器“对于屏幕尺寸x,图片将以y宽度显示”,然后浏览器可以选择最合适的尺寸下载?
  • @ErikH 是的,但是如果您不考虑尺寸参数,浏览器仍然可以(并且将)使用 CSS 来确定图像的宽度,并根据在那。但这确实有一个明显的缺点。浏览器必须先解析 CSS,然后才能开始下载最合适的文件。使用sizes 属性,浏览器可以立即开始下载。
  • 感谢@gijswijs 澄清。那么,您建议保留sizes,还是不保留?
  • 我认为这取决于您的情况。如果 SEO 排名很重要,我不会使用 sizes 而是使用“高度”和“宽度”,以便您在 Pagespeed Insights 上得分更高,这是 SEO 排名的一个因素。如果SEO排名不重要,我会使用sizes
【解决方案2】:

无论你试图做什么,它都会变得复杂,因为你试图完成它。您可以使用相同的图像并使用 CSS 调整其大小。使用媒体查询根据屏幕宽度声明不同大​​小的图像,如下所示。

/* displays the image at 245x600px for small screens */

@media only screen
  and (max-width: /*enter a width in px */) {
    .img-fluid {
      height: 245px;
      width: 600px;
    }
}

/* displays the image at 332x812px for small screens */

@media only screen
  and (min-width: /*enter a width of max-width +1px*/) {
    .img-fluid {
      height: 332px;
      width: 812px;
    }
}
      
&lt;img class="img-fluid" src="image-245w.png" alt="image"&gt; 

【讨论】:

  • 感谢您的回答!这实际上正是我在上面的代码中所做的。通过省略 中的宽度和高度属性,我依赖于我的媒体查询。它工作得很好,但我会通过省略它们来接收 CLS,就像我相信你的代码一样。现在你会想要添加这些属性来避免 CLS,问题是如何在 元素中做到这一点?
  • *另外,我正在以响应方式为同一图像提供不同大小的版本,而不是为不同的视口调整一个图像的大小。这将花费带宽。
  • 调整图片大小不会消耗带宽。提供多个图像确实是因为必须加载多个图像。使用 css 成本调整图像只加载一次图像。例如,如果您将智能手机从纵向切换到横向,图像将按照您的方式重新加载。
  • 是的,它确实会花费带宽,只提供一张图片。想象一下,您有一张巨大的图像要在电影院和智能手机上播放。这张图很重。在智能手机上显示此图像(大幅缩小其尺寸)并不是一个好主意,因为它与电影院的图像相同,因此比为智能手机提供相同图像的更小/更轻版本的带宽要多得多。提供多个图像并不等于所有图像都被使用/加载。只会显示设置条件(媒体查询)所需的那些图像。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-04
  • 2014-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多