网络上大多数图片都是多余的。 如果你能忍受我当一会儿坏人,99% 的图片甚至都没有那么有用 (尽管有一些罕见的例外). 这是因为图片通常不能很好地补充它们应该支持的文本,反而会损害用户,加载时间过长,还会像某种性能税一样耗尽数据上限。
谢天谢地,如今这主要是一个设计问题,因为让图片更有效率,更方便用户使用比以前容易得多。 我们有更好的图片格式,比如 WebP (很快,也许还有 JPEG XL). 我们当然也有 响应式图片 的魔法。 而且还有很多很棒的工具,比如 ImageOptim,以及像 Addy Osmani 的新书 这样的资源。
尽管也许我最喜欢的提高图片性能的方式是使用 延迟加载
<img href="image.webp" alt="Image description" loading="lazy">
这张图片只有在用户滚动到页面下方,图片进入用户视野时才会加载——这样就可以将其从初始页面加载中移除,这简直太好了! 让网页的初始加载速度变得极快非常重要。
但也许有些图片根本不应该加载。 也许在某些情况下,最好让用户选择是否查看图片。 例如,可以查看 NPR 的纯文本版本,四处点击一下。 它是不是… 很棒? 它很易读! 没有任何杂乱无章的东西,它尊重我作为用户,而且——太棒了——它很快。

所以! 如果我们可以在网站上显示图片,但只在点击或轻触时显示呢? 如果我们可以在点击时用真实图片替换占位符,那不是很有趣吗? 就像这样
嗯,我在这里有两个想法,关于如何构建这个小家伙(黄金法则是有很多方法可以构建网络上的任何东西)。
<img>
但不使用src
属性
方法 #1:使用我们可以移除<img>
标签的src
属性来隐藏图片。 然后可以将图片文件放在某个属性中,比如data-src
或其他类似属性,就像这样
<img data-src="image.jpg" src="" alt="Photograph of hot air balloons by Musab Al Rawahi. 144kb">
默认情况下,大多数浏览器会显示一个你可能熟悉的损坏图片图标
好吧,它某种程度上是可访问的。 我猜? 你可以看到alt
标签自动渲染在屏幕上,但使用少量 JavaScript,我们就可以用该属性替换src
document.querySelectorAll("img").forEach((item) => {
item.addEventListener("click", (event) => {
const image = event.target.getAttribute("data-src");
event.target.setAttribute("src", image);
});
});
现在我们可以添加一些样式,哦,不
Ugh. 在某些浏览器中,当图片未加载时,底部会显示一个小的损坏图片图标。 这里的问题是,浏览器不提供使用 CSS 移除损坏图片图标的方法(而且我们可能也不应该被允许这样做)。 对alt
文本进行样式设置也很烦人。 但如果我们完全删除alt
属性,那么损坏图片图标就会消失,尽管这样会使<img>
在没有 JavaScript 的情况下无法使用。 所以,移除alt
文本不可行。
正如我所说:Ugh. 我认为没有办法使这种方法起作用(但请证明我错了!)。
方法 #2:使用链接创建图片
我们拥有的另一个选项是使用普通的超链接,就像这样
<a href="image.jpg">Photograph of hot air balloons by Musab Al Rawahi. 144kb<a>
是的,还没有什么智能的功能——这只会渲染一个指向图片的链接
从可访问性角度来看,这没问题,对吧? 如果我们没有 JavaScript,我们只有一个人可以选择点击的链接。 从性能角度来看,它不可能比纯文本更快!
但从这里开始,我们可以使用 JavaScript 来阻止链接在点击时加载,获取链接中的href
属性,创建一个图片元素,最后将该图片放到页面上,并在完成后删除旧链接
document.querySelectorAll(".load-image").forEach((item) => {
item.addEventListener("click", (event) => {
const href = event.target.getAttribute("href");
const newImage = document.createElement("img");
event.preventDefault();
newImage.setAttribute("src", href);
document.body.insertBefore(newImage, event.target);
event.target.remove();
});
});
我们可以对这个占位符链接进行样式设置,使其看起来比下面显示的样式更漂亮。 但这只是一个例子。 点击链接再次加载图片
就是这样! 它并不突破性,而且我相信在某个时候有人做过类似的事情。 但如果我们想在第一次绘制和初始加载之外,对性能进行非常彻底的改造,我认为这是一个不错的解决方案。 如果我们要创建一个纯文本网站,我认为这绝对是最佳选择。
也许我们还可以用它创建一个 Web 组件,甚至可以检测用户是否启用了 prefers-reduced-data
,然后只有当用户有足够的数据时才会加载图片。 你觉得怎么样?
这真的很棒! 我可能会在我的博客上实现类似的功能。
你不需要 JavaScript,你只需使用经典的复选框技巧(或者根据你想要的 UI 使用单选按钮、焦点等)。 支持
loading=lazy
的浏览器应该会做正确的事情。为了跟进这个问题,我举个例子
在以前为空的
src
值中放置一个微小的透明 1x1px GIF(例如src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
),这样就不会出现损坏图片图标。 即使在文档中多次重复 data-uri 字符串,性能影响也应该是微不足道的,因为像 Gzip 或 Brotli 这样的压缩应该会减轻这种影响。关于我之前的一条评论…
我刚刚重新阅读了这篇文章,意识到我的建议不好,因为这样
alt
文本就不会显示! 我真笨 :) 我想的是非原生延迟加载库,使用像 data-uri 这样的东西是避免损坏图片图标的常用技巧,但它们当然不需要直观地显示 alt 文本…我想使用内联 SVG(带有“点击加载”提示)会起作用吗? 不过,除非你可以使用服务器端工具或 JavaScript 动态生成 SVG 标记并将其中的 alt 文本包括在内,否则你会失去 alt 文本。
如果我想节省带宽,或者只是创建一个交互式部分,这将非常有用。 我喜欢它。
让我想起了 Firefox 的阅读模式。 它试图从所有无关的资料中清理文章。
将 JS 代码放在某个地方会导致进一步的延迟(对于那些痴迷于速度和性能的人来说),首先他们必须点击一些东西,然后执行 JS 代码。 我知道,这很快,但仍然很明显地令人讨厌。
我更愿意在页面加载几秒后自动加载(也许也使用 defer),就像延迟加载一样,但不是在滚动后加载。
人们不需要点击任何东西,视觉体验不会被打断(所以他们永远不会看到一个糟糕的首页),但
alt
属性可能会在首屏上方显示一些内容,比如“图片在这里”。但是,整个逻辑都有缺陷:我认为没有哪个开发者会认为他自己的图片像隐藏在点击后面一样令人讨厌。
为什么不使用一个像素透明图片,并使用以下简单代码
onclick="this.src='realimage.jpg'"
而不是之前所有复杂的 JS 代码。 有时候我们会试图解决一个不存在的问题 :)
另一种方法是使用 details/summary: https://codepen.io/dannievinther/pen/e9e49d946cffa57ba96d76b207a840fa,以及
loading="lazy"
Robert,好主意!另一个想法是,你可以渲染一个超轻的占位符 SVG,它在点击时获取真正的图像。然后,你可以通过使 SVG 与正确图像具有相同的尺寸来防止布局偏移。不过,这比你的示例更费事一些!
感谢你的这些文章,是否可以使用纯 CSS 来做到这一点?在 CSS 中加载 img,然后点击按钮后 img 出现?