HTML深度探索 :img应用与实践
1、定义和用法
-
HTML 元素
<img>
将一张图像嵌入文档。 -
从技术上讲,实际上并没有将图像插入到网页中,而是将图像链接到了网页。
<img>
标签创建了一个容器,用于引用图像。 -
<img>
标签有两个必需的属性:- src - 规定图像的路径;
- alt - 如果由于某种原因无法显示图像,则指定图像的替代文本;同时在无障碍的场景下,该属性也十分有用!
-
注意:另外,始终要指定图像的宽度和高度。如果未指定宽度和高度,则在加载图像时页面可能会闪烁。
当在网页中插入图像但没有明确指定其宽度和高度时,浏览器最初并不知道该图像的实际尺寸。因此,在解析HTML并构建渲染树时,浏览器会预留一个默认大小(通常是32x32像素)或基于CSS的计算值的空间给图像。
一旦图像文件下载并解析,浏览器发现其实际尺寸与预留空间不匹配时,就需要重新布局页面以适应图像的真实大小。这个过程会导致已加载的内容突然移动,从而产生所谓的"内容闪烁"或"重排闪烁",这会降低用户体验,尤其是在移动设备上。
这种布局变化还会影响网页的累积布局偏移(Cumulative Layout Shift, CLS)。CLS度量了用户在页面加载过程中非预期的布局变化程度。较大的CLS值表明页面元素在加载时有较多的移动,这通常被认为是负面的用户体验。因此,为了优化网页性能和提高用户满意度,最好在HTML中为图像指定确切的宽度和高度属性。这样可以让浏览器在加载图像之前就正确预留空间,避免不必要的布局调整和闪烁现象。
示例
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.image {
width: 500px;
height: 500px;
object-fit: cover;
}
</style>
</head>
<body>
<img class="image"
src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg" alt="Ai绘图" />
</body>
</html>
2、图像格式
Web 最常用的图像格式是:
- APNG(动态可移植网络图形)------无损动画序列的不错选择(GIF 性能较差)。
- AVIF(AV1 图像文件格式)------静态图像或动画的不错选择,其性能较好。
- GIF(图像互换格式)------简单图像和动画的不错选择。
- JPEG(联合图像专家组)------有损压缩静态图像的不错选择(目前最流行的格式)。
- PNG(便携式网络图形)------对于无损压缩静态图像而言是不错的选择(质量略好于 JPEG)。
- SVG(可缩放矢量图形)------矢量图像格式。用于必须以不同尺寸准确描绘的图像。
- WebP(网络图片格式)------图像和动画的绝佳选择。
推荐使用 WebP 图像格式,因为它们在静态图像和动画的性能均比 PNG、JPEG、JIF 好得多。
对于必须以不同尺寸准确绘制的图像,则仍然推荐使用 SVG 格式。
3、常用属性
-
alt -- 定义了图像的备用文本描述。
-
title -- 元素的值一般作为提示条(tooltip)呈现给用户,在光标于图片上停下后显示出来。
-
height -- 图像的固有高度,以像素为单位。必须是没有单位的整数值。
-
width -- 图像的宽度,以像素为单位。必须是没有单位的整数。
实际工作中宽度和高度并不会共同使用,因为如果只单独设置了一个属性比如宽度,高度会等比例进行缩放。
- loading -- 指示浏览器应当如何加载该图像。
- eager:立即加载图像,不管它是否在可视视口(visible viewport)之外(默认值)。
- lazy:延迟加载图像,直到它和视口接近到一个计算得到的距离(由浏览器定义)。目的是在需要图像之前,避免加载图像所需要的网络和存储带宽。这通常会提高大多数典型用场景中内容的性能。
html
<img loading="lazy" class="image" src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg" alt="Ai绘图" />
- decoding -- 指定浏览器如何解码图像。可以是 "sync"(同步)或 "async"(异步)。默认为 "sync"。
html
<img decoding="sync" class="image" src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg" alt="Ai绘图" />
decoding 和 loading 属性在
<img>
标签中控制着图像的加载和解码行为,它们各自负责不同的层面。decoding 属性控制图像的解码方式。loading 属性控制图像何时开始加载。
-
crossorigin (crossOrigin) -- 设置跨域资源共享(CORS)属性,允许从不同源加载图像并访问其像素数据。
-
src -- 图像的 URL,这个属性对
<img>
元素来说是必需的。 -
sizes -- 用于响应式设计,告诉浏览器根据不同的视口尺寸选择合适的图像资源。
-
srcset -- 以逗号分隔的一个或多个字符串列表表明一系列用户代理使用的可能的图像。
html
<img src="image-small.jpg"
srcset="image-320w.jpg 320w,
image-480w.jpg 480w,
image-800w.jpg 800w,
image-large.jpg 1200w"
sizes="(max-width: 600px) 100vw,
(max-width: 900px) 50vw,
33vw"
alt="example image">
这个配置告诉浏览器:
在屏幕宽度小于等于600px时,图像应占据整个视口宽度 (100vw)。 在屏幕宽度小于等于900px时,图像应占据视口的一半宽度
(50vw)。 在屏幕宽度大于900px时,图像应占据视口的三分之一宽度 (33vw)。
浏览器会根据当前视口宽度和可用的图像资源来决定加载哪个图像版本,以达到最佳的性能和视觉效果。
html
<picture>
<source media="(max-width: 600px)" srcset="small-image.jpg">
<img src="large-image.jpg" alt="图片描述">
</picture>
4、预加载和懒加载
4.1 预加载
- 图像预加载(Image Preloading)是一种优化技术,它允许在页面的其他部分完全加载之前就开始加载图像,从而提高用户体验,尤其是对于那些位于页面下方但对用户来说很重要的图像。以下是在HTML中实现图像预加载的几种方式:
- 使用
<link rel="preload">
<link rel="preload">
标签允许开发者提前告知浏览器加载特定的资源,包括图像。这是目前推荐的方法,因为它是专门为预加载设计的,而且被广泛支持。
html
<link rel="preload" href="path/to/image.jpg" as="image">
- 这里的 as 属性指定了资源的类型,在这里是图像。这使得浏览器可以优先加载这些图像,即使它们在页面上的位置很远。
- 使用 JavaScript
- 通过JavaScript,你可以动态地创建一个新的 Image 对象并加载图像。这种方法在旧的浏览器中更为常见,但现在由于
<link rel="preload">
的存在而较少使用。
js
// JavaScript 预加载图像示例
window.addEventListener('DOMContentLoaded', function() {
var img = new Image();
img.src = 'path/to/image.jpg';
});
js
const imageUrls = ["image1.jpg", "image2.jpg", "image3.jpg"];
const images = [];
imageUrls.forEach(url => {
const img = new Image();
img.src = url;
images.push(img);
});
- 在上述代码中,通过创建一个新的 Image 对象,并设置其 src 属性,可以在后台加载图像。这样,当需要显示这些图像时,它们已经在浏览器中缓存了。
- 利用 CSS Background Images
- 如果图像将用作背景图像,你可以利用CSS的背景图像属性进行预加载。虽然这不是严格意义上的预加载,但它可以确保背景图像在需要时已经加载完成。
css
/* CSS 预加载背景图像 */
.some-element {
background-image: url('path/to/image.jpg');
}
4.2 懒加载
- 使用 loading 属性(HTML5):HTML5 引入了 loading 属性,可以用于延迟加载图像,仅当图像进入用户视口时才会加载。当用户滚动到图像所在的位置时,浏览器会自动加载图像。
html
<img src="image.jpg" alt="图片描述" loading="lazy">
- 使用 Intersection Observer(JavaScript):Intersection Observer 是一种 JavaScript API,可以监听元素是否进入用户视口,从而实现懒加载
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.image {
width: 500px;
height: 500px;
object-fit: cover;
display: block;
}
</style>
</head>
<body>
<img class="image" src=''
data-src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg"
alt="Ai绘图" />
<img class="image" src=''
data-src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg"
alt="Ai绘图" />
<img class="image" src=''
data-src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg"
alt="Ai绘图" />
<img class="image" src=''
data-src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg"
alt="Ai绘图" />
<img class="image" src=''
data-src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg"
alt="Ai绘图" />
<img class="image" src=''
data-src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg"
alt="Ai绘图" />
<img class="image" src=''
data-src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg"
alt="Ai绘图" />
<img class="image" src=''
data-src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg"
alt="Ai绘图" />
<img class="image" src=''
data-src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg"
alt="Ai绘图" />
<img class="image" src=''
data-src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg"
alt="Ai绘图" />
<img class="image" src=''
data-src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg"
alt="Ai绘图" />
<img class="image" src=''
data-src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/static/dcf2ba9b17ef9b09020a67e42fa6cf28.jpg"
alt="Ai绘图" />
<script>
document.addEventListener('DOMContentLoaded', function () {
const images = document.querySelectorAll('.image');
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// 当图像进入视口时,用实际的图像URL替换占位符
entry.target.src = entry.target.dataset.src;
console.log(entry.target.src);
// 从图像中删除懒加载类,防止重复加载
entry.target.classList.remove('lazy-load');
// 不再观察这个元素,避免不必要的计算
observer.unobserve(entry.target);
}
});
}, {
// 可选:配置观察选项,如根元素、阈值等
threshold: 0.5 // 当元素有50%出现在视口中时就开始加载
});
images.forEach(image => {
observer.observe(image);
});
});
</script>
</body>
</html>
- 在文档加载完成后,选取所有具有image类的图像元素。创建一个新的IntersectionObserver实例,当被观察的元素与视口相交时调用回调函数。遍历所有被观察的图像,如果图像进入了视口,就用data-src属性中存储的URL替换src属性的值,同时删除image类,并停止对该图像的观察。