如何在高分辨率图像完全加载后用更好的图像替换低分辨率背景图像?

How to replace a low resolution background-image with a better one once the higher resolution image has loaded fully?

我希望使用初始绘制加载质量非常低的背景图片,然后根据浏览器的宽度用更高质量的版本替换它。

这是我的 HTML :

<div style="background-image: url('data:image/jpeg;base64,[...]');"></div>

我正在为 div 提供分辨率非常低的 base64 背景图像。

在我的 CSS 中:

@media(max-width:  600px) { div { background-image:  url(600.jpg) !important} }
@media(max-width: 1000px) { div { background-image: url(1000.jpg) !important} }
@media(min-width: 1001px) { div { background-image: url(2200.jpg) !important} }

在这里,我用适合每个屏幕宽度的适当图像覆盖了内联规则。

不幸的是,一旦 CSS 文件加载,浏览器就会用丑陋的部分加载版本的高质量图像替换占位符 base64 图像。

如何等待背景图像完全加载后再换入?

编辑:正如下面评论中的回复,这不是重复的,因为相关答案没有解决响应式图像尺寸问题。

TLDR:
将要在 CSS 中加载的高分辨率图像定义为 "invisible"

#hi-res {
    visibility: hidden;
}

在头部预加载图片

<link rel="preload" href="bg-image-narrow.png" as="image" media="(max-width: 600px)">

然后等待 DOM 完全加载到 "display" 带有

的图像
$(window).load(function(){
    document.getElementById('hi-res').style.visibility='visible';
});


因此,您 运行 遇到的不是 'loading' 问题,而是 'rendering' 问题。浏览器已经在执行它认为您希望它执行的操作,即:在 "loaded" 之后将一幅图像换成另一幅图像,或者更准确地说是 DOM 中的 "found"。那么问题是浏览器遇到(加载)该高分辨率图像的时间比它能够快速渲染它的时间要早​​。本质上,您希望具体地让浏览器等待在可以快速渲染图像的时间点加载图像。

preload 属性应该有助于解决这个问题,因为它本质上是对 DOM 的请求,上面写着:哟,你肯定很快就会需要这个,所以在一切之前抓住它其他和完整。话虽这么说,但这并不意味着一旦浏览器被告知显示图像,它就会很快呈现所有内容。

因此,如果您真的想双击它以确保在浏览器可以将其所有资源用于在屏幕上呈现它之前替代图像不会替换低分辨率图像,您只需将它显式隐藏在视图之外直到其他一切都完成加载。您可以使用 CSS:

#hi-res {
    visibility: hidden;
}

然后 DOM 上的 JS:

$(window).load(function(){
    document.getElementById('hi-res').style.visibility='visible';
});

预加载
回到过去,您可以使用延迟加载,甚至可以在页面底部使用一个简单的 JS 等待脚本。

但是,我认为解决您问题的最佳方法是使用 rel="preload" 中指定的 MDN Web Docs

来简单地预加载您的图像

这可以通过预加载 CSS 文件本身来完成:

<head>
  <meta charset="utf-8">
  <title>JS and CSS preload example</title>

  <link rel="preload" href="style.css" as="style">
  <link rel="preload" href="main.js" as="script">

  <link rel="stylesheet" href="style.css">
</head>

Source

或者更简单的媒体元素本身:

<head>
  <meta charset="utf-8">
  <title>Responsive preload example</title>

  <link rel="preload" href="bg-image-narrow.png" as="image" media="(max-width: 600px)">
  <link rel="preload" href="bg-image-wide.png" as="image" media="(min-width: 601px)">

  <link rel="stylesheet" href="main.css">
</head>

Source