具有 srcset、大小、媒体查询的响应式图像 - 防止加载巨大图像以获得更高的像素密度

Rad*_*472 5 html image srcset pixel-density responsive-images

我很长一段时间都使用图片元素来制作每个视口不同尺寸的响应式图像。它工作得很好,但现在我被迫切换到响应式,并且<img>我尝试将我的图片元素重写为 IMG 样式。srcsetsizes

经过长时间的搜索,我在以下位置找到了很好的文档:

https://www.dofactory.com/html/img/sizes 以及更多详细信息: https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images

带图片的代码是这样的:

<picture>
    <source media="(max-width: 740px)" src="740.jpg" type="image/jpeg">
    <source media="(max-width: 980px)" src="1280.jpg" type="image/jpeg">
    <source media="(max-width: 1280px)" src="1600.jpg" type="image/jpeg">
    <source media="(max-width: 1480px)" src="1920.jpg" type="image/jpeg">
    <img src="740.jpg" title="..." alt="..." />
</picture>  
Run Code Online (Sandbox Code Playgroud)

我将其重写为响应式 img,如下所示:

<img src="740.jpg" title="..." alt="..." 
    srcset="
       740.jpg 740w,
       1280.jpg 1280w,
       1600.jpg 1600w,
       1920.jpg 1920w" 
    sizes="
       (max-width: 740px) 740px,
       (max-width: 980px) 1280px,
       (max-width: 1280px) 1600px,
       (max-width: 1480px) 1920px"
/>
Run Code Online (Sandbox Code Playgroud)

这在浏览器中的第一次测试中似乎效果很好。但后来我注意到在移动设备上它加载了太大的图像。

原因是某些移动设备的像素密度不同,如 响应图像完整指南中所述

您也可以使用 Firefox 的开发工具来模拟: Firefox 开发工具

我尝试通过将代码更改为来解决此问题

<img src="1920.jpg" title="..." alt="..." 
    srcset="
       740.jpg 740w 1x,
       1280.jpg 1280w 1x,
       1600.jpg 1600w 1x,
       1920.jpg 1920w 1x" 
    sizes="
       (max-width: 740px) 740px,
       (max-width: 980px) 1280px,
       (max-width: 1280px) 1600px,
       (max-width: 1480px) 1920px"
/>
Run Code Online (Sandbox Code Playgroud)

不起作用...(它总是加载所有视点的最小图像)

我尝试了使用 img srcset 处理响应式图像中没有媒体查询大小的解决方案

没有像我需要的那样工作......

所以最大的问题是,如何组合宽度和密度的选择器。

在我的示例中,它应该加载:

  • 740.jpg 宽度为 0-740
  • 1280.jpg 宽度 740-980
  • 1600.jpg 宽度 980-1280
  • 1920.jpg 一切更大

我不希望它为像素密度更大的设备加载更大的图像。

我知道 Stackoverflow 中有很多类似的问题,我花了几周的时间寻找可行的解决方案,但似乎没有任何效果像预期的那样,所以我希望有人可以提供解决方案

更新: 我发现,有一个 gitlab 问题讨论了这个问题。

2

(请参阅响应式图像导致性能问题

但目前看来,这个问题还没有最终的解决方案。

如果有人能提供新想法,我将非常高兴。

Rad*_*472 2

我找到了两种可能的解决方案:

两者都使用最小分辨率媒体查询来定义每个像素密度的单独大小。我用一个比问题更简单的例子来解释它:

想法1

<img src="500.jpg" title="..." alt="..." 
    srcset="
       500.jpg 500w,
       1000.jpg 1000w"
    sizes="
       (min-resolution: 3dppx) 33vw,
       (min-resolution: 2dppx) 50vw,
       (min-resolution: 1dppx) 100vw"
/>
Run Code Online (Sandbox Code Playgroud)

我使用了这些100vh示例,并“恢复”浏览器拍摄的图像是current_with * pixel-density.

此解决方案适用于全屏图像,但您可以使用自定义视口。

想法2

<img src="500.jpg" title="..." alt="..." 
    srcset="
       500.jpg 500w,
       1000.jpg 1000w"
    sizes="
       (min-resolution: 3dppx) and (max-width: 600px) 1500px,
       (min-resolution: 3dppx) and (max-width: 1200px) 2000px,

       (min-resolution: 2dppx) and (max-width: 600px) 1000px,
       (min-resolution: 2dppx) and (max-width: 1200px) 2000px,

       (min-resolution: 1dppx) and (max-width: 600px) 500px,
       (min-resolution: 1dppx) and (max-width: 1200px) 1000px"
/>
Run Code Online (Sandbox Code Playgroud)

我根据屏幕宽度创建了类似的媒体查询,但添加了“恢复”浏览器拍摄的图像的尺寸current_with * pixel-density

此解决方案适用于所有图像,即使它们不是全尺寸。在这里您可以使用自定义视口,但代码相对较多。

两者背后的基本思想:

  • 例如,对于像素密度 2x 和 500px 屏幕宽度,浏览器选择双倍尺寸的 srcset,该尺寸在媒体查询尺寸中定义,并采用 1000px - 图像
  • 所以我尝试为我所需大小的两倍(例如 1000px)定义新的媒体查询,当它按像素比设置时,浏览器将获得我所需的 500px

在夏季,这意味着:

如果您想恢复浏览器为具有大像素密度的移动设备拍摄更大图像的效果,您必须为每个像素密度的尺寸计算新值。

对于这两种解决方案,您也应该通过 css 定义显示尺寸。

例如,这个简单的 php 代码示例表明:

<?php
  $viewport = [
    // Viewport => Image-Size
    600  => 500,
    1200 => 1000
  ];

  // walk over all pixel-densities
  for($i=3; $i>0; $i--) {
    foreach($viewport as $vp => $w) 
      echo "(min-resolution: {$i}dppx) and (max-width: {$vp}px) "
            .floor($w/$i) . "px,\n";
  }
?>
Run Code Online (Sandbox Code Playgroud)