0%

图片与多媒体

图片与多媒体

图片和多媒体内容是现代网页的重要组成部分,它们极大地丰富了用户体验。HTML5 提供了强大的图片和多媒体支持,包括响应式图片、矢量图形、音频视频等。本文档将详细介绍如何使用这些元素以及相关的性能优化技巧。

1. 图片基础 - <img> 元素

1.1 基本用法

<img> 元素用于在页面中嵌入图片,是一个自闭合标签(void element)。

1
<img src="image.jpg" alt="图片描述">

必需属性

  • src:图片的 URL 或路径

推荐属性

  • alt:替代文本,当图片无法显示时显示(对可访问性很重要)

1.2 src 属性

src 指定图片资源的路径,可以是相对路径、绝对路径或完整的 URL。

1
2
3
4
5
6
7
8
9
10
11
<!-- 相对路径 -->
<img src="images/photo.jpg" alt="照片">

<!-- 绝对路径 -->
<img src="/images/photo.jpg" alt="照片">

<!-- 完整 URL -->
<img src="https://www.example.com/images/photo.jpg" alt="照片">

<!-- 协议相对 URL(不推荐,可能有安全问题) -->
<img src="//example.com/images/photo.jpg" alt="照片">

1.3 alt 属性(替代文本)

alt 属性是图片最重要的可访问性属性,当图片无法加载时,会显示 alt 文本。

1
<img src="logo.png" alt="公司 Logo">

最佳实践

  • 必须提供 alt 属性:即使是装饰性图片也应设置 alt=""(空字符串)
  • 描述图片内容:对于有意义的图片,alt 应该准确描述图片内容
  • 简洁明了:通常不超过 125 个字符
  • 不要包含”图片”等词:屏幕阅读器会自动读出,避免冗余
  • 功能性图片:描述功能而非外观(如”提交表单”而非”蓝色按钮”)

示例

1
2
3
4
5
6
7
8
<!-- 好的做法 -->
<img src="user-avatar.jpg" alt="张三的头像">
<img src="chart.png" alt="2024年销售额增长趋势图">
<img src="decorative-line.png" alt=""><!-- 装饰性图片,空 alt -->

<!-- 不好的做法 -->
<img src="logo.png" alt="这是一个 Logo 图片"><!-- 冗余 -->
<img src="button.png" alt=""><!-- 功能性图片需要描述 -->

1.4 title 属性(提示文本)

title 属性提供额外的提示信息,当鼠标悬停在图片上时会显示工具提示。

1
<img src="photo.jpg" alt="风景照片" title="拍摄于2024年1月,地点:黄山">

注意

  • title 不是 alt 的替代品
  • title 主要用于提供额外信息,而非替代文本
  • 屏幕阅读器的支持不一致,不应依赖它来提供关键信息
  • 移动设备上无法显示 title 提示

使用场景

  • 提供图片的版权信息
  • 显示图片的拍摄时间、地点等元数据
  • 提供额外的说明信息

1.5 width 和 height 属性

设置图片的宽度和高度(像素值)。

1
<img src="photo.jpg" alt="照片" width="800" height="600">

现代做法:推荐使用 CSS 而不是 HTML 属性:

1
2
3
4
5
6
7
8
9
10
<img src="photo.jpg" alt="照片" style="width: 800px; height: 600px;">

<!-- 或使用 CSS 类 -->
<img src="photo.jpg" alt="照片" class="responsive-img">
<style>
.responsive-img {
width: 100%;
height: auto;
}
</style>

设置尺寸的好处

  • 防止布局偏移(CLS - Cumulative Layout Shift)
  • 浏览器可以预留空间,避免内容跳动
  • 提升页面加载性能

响应式图片(推荐)

1
2
3
4
<img 
src="photo.jpg"
alt="照片"
style="max-width: 100%; height: auto;">

1.6 loading 属性(懒加载)

loading 属性控制图片的加载时机,用于实现懒加载(lazy loading)。

1
2
3
4
5
<!-- 立即加载(默认) -->
<img src="photo.jpg" alt="照片" loading="eager">

<!-- 延迟加载(进入视口时再加载) -->
<img src="photo.jpg" alt="照片" loading="lazy">

属性值

  • eager:立即加载(默认值)
  • lazy:延迟加载,当图片接近视口时再加载

使用场景

  • 首屏图片:使用 loading="eager"(或不设置,默认就是 eager)
  • 首屏外图片:使用 loading="lazy" 延迟加载
  • 轮播图:非第一张可以使用 loading="lazy"

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 首屏 banner,立即加载 -->
<img src="banner.jpg" alt="首页横幅" loading="eager">

<!-- 内容区域图片,延迟加载 -->
<article>
<h2>文章标题</h2>
<img src="article-image.jpg" alt="文章配图" loading="lazy">
</article>

<!-- 图片画廊,第一张立即加载,其他延迟加载 -->
<div class="gallery">
<img src="photo1.jpg" alt="照片1" loading="eager">
<img src="photo2.jpg" alt="照片2" loading="lazy">
<img src="photo3.jpg" alt="照片3" loading="lazy">
</div>

浏览器支持

  • Chrome 76+
  • Firefox 75+
  • Edge 79+
  • Safari 15.4+

降级方案:对于不支持 loading="lazy" 的浏览器,可以使用 JavaScript 实现懒加载。

1.7 srcset 和 sizes 属性(响应式图片)

srcsetsizes 属性用于实现响应式图片,根据设备像素密度和屏幕宽度选择最合适的图片。

srcset 属性

srcset 提供多个图片源,让浏览器根据设备特性选择。

基于像素密度(DPR)

1
2
3
4
5
6
7
8
<img 
src="photo.jpg"
alt="照片"
srcset="
photo-1x.jpg 1x,
photo-2x.jpg 2x,
photo-3x.jpg 3x
">
  • 1x:标准分辨率(1 DPR)
  • 2x:高分辨率(Retina 显示屏,2 DPR)
  • 3x:超高清(3 DPR)

基于宽度描述符(推荐)

1
2
3
4
5
6
7
8
9
10
<img 
src="photo.jpg"
alt="照片"
srcset="
photo-small.jpg 400w,
photo-medium.jpg 800w,
photo-large.jpg 1200w
"
sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px"
src="photo-medium.jpg">
  • 400w:图片实际宽度为 400 像素
  • 800w:图片实际宽度为 800 像素
  • 1200w:图片实际宽度为 1200 像素

sizes 属性

sizes 告诉浏览器在不同屏幕尺寸下,图片的显示宽度是多少。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<img 
src="photo.jpg"
alt="照片"
srcset="
photo-small.jpg 400w,
photo-medium.jpg 800w,
photo-large.jpg 1200w,
photo-xlarge.jpg 1600w
"
sizes="
(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
800px
">

sizes 语法说明

  • (max-width: 600px) 100vw:屏幕宽度 ≤ 600px 时,图片占满视口宽度
  • (max-width: 1200px) 50vw:屏幕宽度 ≤ 1200px 时,图片占视口宽度的 50%
  • 800px:默认情况下,图片宽度为 800px

完整示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<img 
src="hero-small.jpg"
alt="英雄图片"
srcset="
hero-small.jpg 600w,
hero-medium.jpg 1200w,
hero-large.jpg 1800w,
hero-xlarge.jpg 2400w
"
sizes="
(max-width: 768px) 100vw,
(max-width: 1200px) 90vw,
1200px
">

实际工作流程

  1. 浏览器读取 sizes 属性,确定图片在页面上的显示宽度
  2. 根据设备像素比(DPR)计算需要的实际像素宽度
  3. srcset 中选择最接近且大于所需尺寸的图片
  4. 下载并显示选中的图片

1.8 decoding 属性

decoding 属性提示浏览器如何解码图片。

1
<img src="photo.jpg" alt="照片" decoding="async">

属性值

  • sync:同步解码(可能阻塞页面渲染)
  • async:异步解码(推荐,不阻塞渲染)
  • auto:浏览器决定(默认)

使用建议

  • 关键图片可以使用 sync
  • 非关键图片使用 async(推荐)
  • 大多数情况下使用默认值 auto 即可

1.9 fetchpriority 属性

fetchpriority 属性提示浏览器图片的加载优先级。

1
2
3
4
5
6
7
8
<!-- 高优先级(首屏关键图片) -->
<img src="hero.jpg" alt="首屏图片" fetchpriority="high">

<!-- 低优先级(非关键图片) -->
<img src="thumbnail.jpg" alt="缩略图" fetchpriority="low">

<!-- 自动(默认) -->
<img src="photo.jpg" alt="照片" fetchpriority="auto">

使用场景

  • 首屏关键图片:fetchpriority="high"
  • Logo、图标等:fetchpriority="high"
  • 首屏外的图片:fetchpriority="low" 或默认

2. 矢量图形 - SVG

2.1 SVG 简介

SVG(Scalable Vector Graphics,可缩放矢量图形)是基于 XML 的矢量图形格式。与位图(PNG、JPG)不同,SVG 可以无损缩放而不失真。

SVG 的优势

  • 无损缩放,任意尺寸都清晰
  • 文件通常较小(简单图形)
  • 可以通过 CSS 和 JavaScript 控制
  • 可搜索、可访问(支持文本)

2.2 在 HTML 中使用 SVG

方法 1:作为图片文件

1
<img src="logo.svg" alt="Logo">

优点:简单,可以缓存
缺点:无法通过 CSS/JS 修改样式,无法添加交互

方法 2:内联 SVG(推荐)

1
2
3
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="40" fill="blue" />
</svg>

优点

  • 可以通过 CSS 修改样式
  • 可以通过 JavaScript 添加交互
  • 减少 HTTP 请求

缺点

  • HTML 文件变大
  • 无法单独缓存
  • 重复使用时不方便

方法 3:作为背景图片

1
2
3
4
5
.logo {
background-image: url('logo.svg');
background-size: contain;
background-repeat: no-repeat;
}

2.3 SVG 基础元素

基本图形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<svg width="200" height="200" viewBox="0 0 200 200">
<!-- 矩形 -->
<rect x="10" y="10" width="80" height="60" fill="red" />

<!-- 圆形 -->
<circle cx="150" cy="50" r="30" fill="blue" />

<!-- 椭圆 -->
<ellipse cx="100" cy="120" rx="50" ry="30" fill="green" />

<!-- 直线 -->
<line x1="10" y1="180" x2="190" y2="180" stroke="black" stroke-width="2" />

<!-- 折线 -->
<polyline points="20,100 60,80 100,120 140,100"
fill="none"
stroke="purple"
stroke-width="2" />

<!-- 多边形 -->
<polygon points="150,120 170,160 130,160" fill="orange" />

<!-- 路径(最强大) -->
<path d="M 50 150 L 100 100 Q 150 50 200 100"
fill="none"
stroke="brown"
stroke-width="2" />
</svg>

文本

1
2
3
4
5
<svg width="200" height="100">
<text x="10" y="50" font-family="Arial" font-size="24" fill="black">
SVG 文本
</text>
</svg>

2.4 SVG 图标系统 - <use> 元素

<use> 元素用于重用已定义的 SVG 元素,非常适合创建图标系统。

定义和使用符号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<svg style="display: none;">
<!-- 定义可重用的图标 -->
<symbol id="icon-home" viewBox="0 0 24 24">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</symbol>

<symbol id="icon-search" viewBox="0 0 24 24">
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
</symbol>
</svg>

<!-- 使用图标 -->
<svg class="icon">
<use href="#icon-home"></use>
</svg>

<svg class="icon">
<use href="#icon-search"></use>
</svg>

<style>
.icon {
width: 24px;
height: 24px;
fill: currentColor; /* 使用当前文字颜色 */
}
</style>

外部 SVG 文件引用

sprite.svg

1
2
3
4
5
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="icon-star" viewBox="0 0 24 24">
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/>
</symbol>
</svg>

HTML 中使用

1
2
3
<svg class="icon">
<use href="sprite.svg#icon-star"></use>
</svg>

注意:外部文件引用需要服务器支持(不能使用 file:// 协议)。

2.5 SVG 样式控制

SVG 可以通过 CSS 控制样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<svg class="icon-button" width="50" height="50">
<circle cx="25" cy="25" r="20" class="circle" />
<text x="25" y="30" text-anchor="middle" class="text">OK</text>
</svg>

<style>
.icon-button {
cursor: pointer;
}

.circle {
fill: #4285f4;
transition: fill 0.3s;
}

.icon-button:hover .circle {
fill: #357ae8;
}

.text {
fill: white;
font-family: Arial;
font-size: 14px;
font-weight: bold;
}
</style>

2.6 SVG 响应式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- 方法 1:使用 viewBox,通过 CSS 控制大小 -->
<svg viewBox="0 0 100 100" class="responsive-svg">
<circle cx="50" cy="50" r="40" />
</svg>

<style>
.responsive-svg {
width: 100%;
height: auto;
max-width: 500px;
}
</style>

<!-- 方法 2:作为 img 使用时,使用 CSS -->
<img src="logo.svg" alt="Logo" class="responsive-logo">

<style>
.responsive-logo {
width: 100%;
height: auto;
max-width: 200px;
}
</style>

3. 响应式图片 - <picture> 元素

<picture> 元素提供更灵活的响应式图片解决方案,可以根据不同条件选择不同的图片源。

3.1 picture 基础语法

1
2
3
4
5
<picture>
<source srcset="image-large.jpg" media="(min-width: 1200px)">
<source srcset="image-medium.jpg" media="(min-width: 768px)">
<img src="image-small.jpg" alt="响应式图片">
</picture>

工作原理

  1. 浏览器从上到下检查每个 <source>media 条件
  2. 选择第一个匹配条件的 <source>
  3. 如果没有匹配的 <source>,使用 <img> 作为后备

3.2 基于屏幕宽度的响应式

1
2
3
4
5
6
7
8
9
10
<picture>
<!-- 大屏幕(桌面) -->
<source srcset="hero-desktop.jpg" media="(min-width: 1200px)">

<!-- 中等屏幕(平板) -->
<source srcset="hero-tablet.jpg" media="(min-width: 768px)">

<!-- 小屏幕(手机)- 默认 -->
<img src="hero-mobile.jpg" alt="英雄图片">
</picture>

3.3 基于图片格式的支持(格式选择)

根据浏览器对图片格式的支持选择最优格式:

1
2
3
4
5
6
7
8
9
10
<picture>
<!-- 优先使用 AVIF(最佳压缩) -->
<source srcset="photo.avif" type="image/avif">

<!-- 其次使用 WebP -->
<source srcset="photo.webp" type="image/webp">

<!-- 最后使用 JPG(兼容所有浏览器) -->
<img src="photo.jpg" alt="照片">
</picture>

支持的图片格式类型

  • image/avif:AVIF 格式(最佳压缩比)
  • image/webp:WebP 格式(很好的压缩比,广泛支持)
  • image/apng:APNG 格式(动画 PNG)
  • image/png:PNG 格式
  • image/jpegimage/jpg:JPEG 格式

3.4 组合使用:格式 + 响应式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<picture>
<!-- 大屏幕,优先使用 AVIF -->
<source
srcset="hero-large.avif"
media="(min-width: 1200px)"
type="image/avif">
<source
srcset="hero-large.webp"
media="(min-width: 1200px)"
type="image/webp">

<!-- 中等屏幕 -->
<source
srcset="hero-medium.avif"
media="(min-width: 768px)"
type="image/avif">
<source
srcset="hero-medium.webp"
media="(min-width: 768px)"
type="image/webp">

<!-- 小屏幕 -->
<source srcset="hero-small.avif" type="image/avif">
<source srcset="hero-small.webp" type="image/webp">

<!-- 最终后备方案 -->
<img src="hero-small.jpg" alt="英雄图片" loading="lazy">
</picture>

3.5 基于像素密度的响应式

1
2
3
4
5
6
7
<picture>
<!-- 高分辨率设备 -->
<source srcset="icon@2x.png 2x, icon@3x.png 3x">

<!-- 标准分辨率(默认) -->
<img src="icon.png" alt="图标">
</picture>

3.6 picture 与 srcset/sizes 结合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<picture>
<source
srcset="
hero-small.webp 600w,
hero-medium.webp 1200w,
hero-large.webp 1800w
"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 90vw, 1200px"
type="image/webp">

<img
src="hero-medium.jpg"
alt="英雄图片"
srcset="
hero-small.jpg 600w,
hero-medium.jpg 1200w,
hero-large.jpg 1800w
"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 90vw, 1200px">
</picture>

4. 音频 - <audio> 元素

4.1 基本用法

<audio> 元素用于在页面中嵌入音频内容。

1
<audio src="music.mp3" controls></audio>

4.2 常用属性

属性 说明 示例值
src 音频文件 URL src="audio.mp3"
controls 显示播放控制栏 controls(布尔属性)
autoplay 自动播放 autoplay(注意:浏览器可能阻止)
loop 循环播放 loop
muted 静音 muted
preload 预加载策略 nonemetadataauto

4.3 完整示例

1
2
3
4
5
6
7
<audio 
src="background-music.mp3"
controls
loop
preload="metadata">
您的浏览器不支持 audio 元素。
</audio>

多格式支持(推荐):

1
2
3
4
5
6
<audio controls>
<source src="audio.mp3" type="audio/mpeg">
<source src="audio.ogg" type="audio/ogg">
<source src="audio.wav" type="audio/wav">
<p>您的浏览器不支持 HTML5 音频播放。</p>
</audio>

常用音频格式

  • MP3(.mp3audio/mpeg):最广泛支持
  • OGG(.oggaudio/ogg):开源格式
  • WAV(.wavaudio/wav):无损,文件较大
  • AAC(.aacaudio/aac):较好的压缩比

4.4 preload 属性

控制音频的预加载行为:

1
2
3
4
5
6
7
8
<!-- 不预加载(节省带宽) -->
<audio src="audio.mp3" controls preload="none"></audio>

<!-- 只加载元数据(时长、大小等) -->
<audio src="audio.mp3" controls preload="metadata"></audio>

<!-- 预加载整个文件(默认) -->
<audio src="audio.mp3" controls preload="auto"></audio>

4.5 自定义音频控制

使用 JavaScript API 可以完全自定义音频控制界面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<audio id="myAudio" src="music.mp3"></audio>

<button onclick="playAudio()">播放</button>
<button onclick="pauseAudio()">暂停</button>
<button onclick="stopAudio()">停止</button>
<input type="range" id="volume" min="0" max="1" step="0.1" value="1" onchange="setVolume()">
<span id="time">0:00 / 0:00</span>

<script>
const audio = document.getElementById('myAudio');

function playAudio() {
audio.play();
}

function pauseAudio() {
audio.pause();
}

function stopAudio() {
audio.pause();
audio.currentTime = 0;
}

function setVolume() {
const volume = document.getElementById('volume').value;
audio.volume = volume;
}

// 更新时间显示
audio.addEventListener('timeupdate', function() {
const current = formatTime(audio.currentTime);
const duration = formatTime(audio.duration);
document.getElementById('time').textContent = `${current} / ${duration}`;
});

function formatTime(seconds) {
if (isNaN(seconds)) return '0:00';
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs.toString().padStart(2, '0')}`;
}
</script>

5. 视频 - <video> 元素

5.1 基本用法

<video> 元素用于在页面中嵌入视频内容。

1
<video src="movie.mp4" controls width="640" height="360"></video>

5.2 常用属性

属性 说明 示例值
src 视频文件 URL src="video.mp4"
controls 显示播放控制栏 controls
autoplay 自动播放 autoplay(通常需要 muted)
loop 循环播放 loop
muted 静音 muted
preload 预加载策略 nonemetadataauto
poster 视频封面图片 poster="poster.jpg"
width / height 视频尺寸 width="640" height="360"
playsinline 内联播放(移动端) playsinline

5.3 完整示例

1
2
3
4
5
6
7
8
9
<video 
src="video.mp4"
controls
width="800"
height="450"
poster="poster.jpg"
preload="metadata">
您的浏览器不支持 video 元素。
</video>

多格式支持(强烈推荐):

1
2
3
4
5
6
<video controls width="800" height="450" poster="poster.jpg">
<source src="video.mp4" type="video/mp4">
<source src="video.webm" type="video/webm">
<source src="video.ogg" type="video/ogg">
<p>您的浏览器不支持 HTML5 视频播放。</p>
</video>

常用视频格式

  • MP4(.mp4video/mp4):H.264 编码,最广泛支持
  • WebM(.webmvideo/webm):VP8/VP9 编码,开源,文件较小
  • OGG(.ogvvideo/ogg):开源格式

5.4 响应式视频

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div class="video-container">
<video controls poster="poster.jpg">
<source src="video.mp4" type="video/mp4">
<source src="video.webm" type="video/webm">
</video>
</div>

<style>
.video-container {
position: relative;
padding-bottom: 56.25%; /* 16:9 比例 */
height: 0;
overflow: hidden;
}

.video-container video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>

5.5 自定义视频控制栏

使用 JavaScript 可以创建完全自定义的视频控制界面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<div class="custom-video-player">
<video id="myVideo" src="video.mp4" poster="poster.jpg"></video>

<div class="controls">
<button id="playBtn">播放</button>
<button id="pauseBtn">暂停</button>
<input type="range" id="seekBar" min="0" max="100" value="0">
<input type="range" id="volumeBar" min="0" max="100" value="100">
<button id="fullscreenBtn">全屏</button>
<span id="timeDisplay">0:00 / 0:00</span>
</div>
</div>

<style>
.custom-video-player {
max-width: 800px;
margin: 0 auto;
}

.custom-video-player video {
width: 100%;
display: block;
}

.controls {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
background: #000;
color: white;
}

.controls button {
padding: 5px 15px;
cursor: pointer;
}

.controls input[type="range"] {
flex: 1;
}
</style>

<script>
const video = document.getElementById('myVideo');
const playBtn = document.getElementById('playBtn');
const pauseBtn = document.getElementById('pauseBtn');
const seekBar = document.getElementById('seekBar');
const volumeBar = document.getElementById('volumeBar');
const fullscreenBtn = document.getElementById('fullscreenBtn');
const timeDisplay = document.getElementById('timeDisplay');

// 播放/暂停
playBtn.addEventListener('click', () => video.play());
pauseBtn.addEventListener('click', () => video.pause());

// 进度条
video.addEventListener('timeupdate', () => {
const value = (100 / video.duration) * video.currentTime;
seekBar.value = value;
updateTimeDisplay();
});

seekBar.addEventListener('input', () => {
const time = video.duration * (seekBar.value / 100);
video.currentTime = time;
});

// 音量控制
volumeBar.addEventListener('input', () => {
video.volume = volumeBar.value / 100;
});

// 全屏
fullscreenBtn.addEventListener('click', () => {
if (video.requestFullscreen) {
video.requestFullscreen();
} else if (video.webkitRequestFullscreen) {
video.webkitRequestFullscreen();
} else if (video.mozRequestFullScreen) {
video.mozRequestFullScreen();
}
});

// 更新时间显示
function updateTimeDisplay() {
const current = formatTime(video.currentTime);
const duration = formatTime(video.duration);
timeDisplay.textContent = `${current} / ${duration}`;
}

function formatTime(seconds) {
if (isNaN(seconds)) return '0:00';
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs.toString().padStart(2, '0')}`;
}

// 视频加载完成后更新进度条最大值
video.addEventListener('loadedmetadata', () => {
seekBar.max = 100;
updateTimeDisplay();
});
</script>

5.6 视频事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const video = document.querySelector('video');

// 视频开始播放
video.addEventListener('play', () => console.log('开始播放'));

// 视频暂停
video.addEventListener('pause', () => console.log('暂停'));

// 视频结束
video.addEventListener('ended', () => console.log('播放结束'));

// 视频加载完成
video.addEventListener('loadeddata', () => console.log('数据加载完成'));

// 元数据加载完成(时长、尺寸等)
video.addEventListener('loadedmetadata', () => {
console.log('时长:', video.duration);
console.log('尺寸:', video.videoWidth, 'x', video.videoHeight);
});

// 等待数据缓冲
video.addEventListener('waiting', () => console.log('缓冲中...'));
video.addEventListener('canplay', () => console.log('可以播放'));

// 错误处理
video.addEventListener('error', () => {
console.error('视频加载错误');
});

6. 图片格式选择与性能优化

6.1 常用图片格式对比

格式 类型 特点 适用场景 浏览器支持
JPEG/JPG 位图 有损压缩,文件小,不支持透明 照片、复杂图像 全支持
PNG 位图 无损/有损,支持透明 Logo、图标、需要透明的图片 全支持
GIF 位图 支持动画,颜色有限(256色) 简单动画 全支持
WebP 位图 现代格式,压缩比高,支持透明和动画 替代 JPG/PNG,现代浏览器 Chrome、Firefox、Edge、Opera
AVIF 位图 最新格式,最佳压缩比 替代所有位图格式 Chrome 85+、Firefox 93+
SVG 矢量 无损缩放,可编辑 图标、简单图形、Logo 全支持

6.2 格式选择建议

照片类图片

1
2
3
4
5
6
<!-- 优先使用现代格式,JPG 作为后备 -->
<picture>
<source srcset="photo.avif" type="image/avif">
<source srcset="photo.webp" type="image/webp">
<img src="photo.jpg" alt="照片">
</picture>

图标和简单图形

1
2
3
4
5
6
7
8
<!-- 优先使用 SVG -->
<img src="icon.svg" alt="图标">

<!-- 如果需要位图,使用 PNG 或 WebP -->
<picture>
<source srcset="icon.webp" type="image/webp">
<img src="icon.png" alt="图标">
</picture>

需要透明的图片

1
2
3
4
5
<!-- 使用 PNG 或 WebP -->
<picture>
<source srcset="logo.webp" type="image/webp">
<img src="logo.png" alt="Logo">
</picture>

6.3 图片优化技巧

1. 选择合适的尺寸

1
2
3
4
5
6
<!-- 不要使用过大的图片 -->
<!-- 不好的做法:使用 2000x2000 的图片显示为 200x200 -->
<img src="large-image.jpg" width="200" height="200" alt="小图">

<!-- 好的做法:提供合适尺寸的图片 -->
<img src="small-image.jpg" width="200" height="200" alt="小图">

2. 使用响应式图片

1
2
3
4
5
6
7
8
9
10
11
<picture>
<source
srcset="hero-large.webp 1920w, hero-medium.webp 960w, hero-small.webp 480w"
type="image/webp">
<img
src="hero-medium.jpg"
srcset="hero-large.jpg 1920w, hero-medium.jpg 960w, hero-small.jpg 480w"
sizes="(max-width: 768px) 100vw, 1200px"
alt="英雄图片"
loading="lazy">
</picture>

3. 懒加载非关键图片

1
<img src="content-image.jpg" alt="内容图片" loading="lazy">

4. 使用占位符和骨架屏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- 占位符(Base64 编码的小图片) -->
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='300'%3E%3Crect fill='%23ddd' width='400' height='300'/%3E%3C/svg%3E"
data-src="real-image.jpg"
alt="图片"
class="lazy-image">

<script>
// 图片懒加载
const lazyImages = document.querySelectorAll('.lazy-image');

const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy-image');
observer.unobserve(img);
}
});
});

lazyImages.forEach(img => imageObserver.observe(img));
</script>

5. 骨架屏(Skeleton Screen)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<div class="image-container">
<!-- 骨架屏 -->
<div class="skeleton" id="skeleton"></div>
<!-- 实际图片(初始隐藏) -->
<img
src="image.jpg"
alt="图片"
id="realImage"
style="display: none;"
onload="showImage()">
</div>

<style>
.skeleton {
width: 100%;
height: 300px;
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: loading 1.5s infinite;
}

@keyframes loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
</style>

<script>
function showImage() {
document.getElementById('skeleton').style.display = 'none';
document.getElementById('realImage').style.display = 'block';
}
</script>

6.4 图片加载性能指标

关注以下 Core Web Vitals 指标:

  • **LCP (Largest Contentful Paint)**:最大内容绘制时间,首屏大图应快速加载
  • **CLS (Cumulative Layout Shift)**:累积布局偏移,设置图片尺寸避免布局跳动
  • **FID (First Input Delay)**:首次输入延迟,避免图片加载阻塞交互

优化示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- 优化 LCP:关键图片使用 fetchpriority="high" -->
<img
src="hero-image.webp"
alt="首屏图片"
fetchpriority="high"
loading="eager"
width="1200"
height="600">

<!-- 优化 CLS:设置明确的尺寸 -->
<img
src="content-image.jpg"
alt="内容图片"
width="800"
height="600"
style="width: 100%; height: auto;">

<!-- 优化 FID:非关键图片延迟加载 -->
<img
src="thumbnail.jpg"
alt="缩略图"
loading="lazy"
fetchpriority="low">

7. 实际应用示例

7.1 完整的响应式图片方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<picture>
<!-- 大屏幕,现代格式 -->
<source
media="(min-width: 1200px)"
srcset="
hero-xlarge.avif 2400w,
hero-large.avif 1920w
"
sizes="1920px"
type="image/avif">
<source
media="(min-width: 1200px)"
srcset="
hero-xlarge.webp 2400w,
hero-large.webp 1920w
"
sizes="1920px"
type="image/webp">

<!-- 中等屏幕 -->
<source
media="(min-width: 768px)"
srcset="
hero-medium.avif 1200w,
hero-medium.webp 1200w
"
sizes="100vw"
type="image/avif">
<source
media="(min-width: 768px)"
srcset="hero-medium.webp 1200w"
sizes="100vw"
type="image/webp">

<!-- 小屏幕 -->
<source
srcset="hero-small.avif 800w"
type="image/avif">
<source
srcset="hero-small.webp 800w"
type="image/webp">

<!-- 最终后备 -->
<img
src="hero-small.jpg"
srcset="hero-small.jpg 800w, hero-medium.jpg 1200w, hero-large.jpg 1920w"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 100vw, 1920px"
alt="英雄图片"
width="1920"
height="1080"
loading="eager"
fetchpriority="high">
</picture>

7.2 图片画廊

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<div class="gallery">
<picture>
<source srcset="photo1.avif" type="image/avif">
<source srcset="photo1.webp" type="image/webp">
<img
src="photo1.jpg"
alt="照片1"
loading="eager"
onclick="openLightbox('photo1.jpg')">
</picture>

<picture>
<source srcset="photo2.avif" type="image/avif">
<source srcset="photo2.webp" type="image/webp">
<img
src="photo2.jpg"
alt="照片2"
loading="lazy"
onclick="openLightbox('photo2.jpg')">
</picture>

<!-- 更多图片... -->
</div>

<style>
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
}

.gallery img {
width: 100%;
height: auto;
cursor: pointer;
transition: transform 0.3s;
}

.gallery img:hover {
transform: scale(1.05);
}
</style>

7.3 视频播放器组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<div class="video-player">
<video id="video" poster="poster.jpg">
<source src="video.mp4" type="video/mp4">
<source src="video.webm" type="video/webm">
</video>

<div class="custom-controls">
<button class="play-pause"></button>
<div class="progress-container">
<div class="progress-bar"></div>
</div>
<span class="time">0:00 / 0:00</span>
<input type="range" class="volume" min="0" max="100" value="100">
<button class="fullscreen"></button>
</div>
</div>

<style>
.video-player {
max-width: 800px;
margin: 0 auto;
background: #000;
}

.video-player video {
width: 100%;
display: block;
}

.custom-controls {
display: flex;
align-items: center;
padding: 10px;
background: rgba(0, 0, 0, 0.8);
color: white;
}

.progress-container {
flex: 1;
height: 4px;
background: #555;
margin: 0 10px;
cursor: pointer;
}

.progress-bar {
height: 100%;
background: #fff;
width: 0%;
}

.volume {
width: 100px;
margin: 0 10px;
}
</style>

<script>
// 实现自定义控制逻辑(参考前面的自定义视频控制示例)
</script>

总结

本文档详细介绍了 HTML 中图片和多媒体的使用:

  1. <img> 元素:基础用法、alt/title、srcset/sizes、懒加载等
  2. SVG 矢量图形:内联使用、图标系统、样式控制
  3. <picture> 响应式图片:格式选择、屏幕适配
  4. <audio> 音频:基本用法、自定义控制
  5. <video> 视频:基本用法、响应式、自定义控制栏
  6. 性能优化:格式选择、懒加载、占位符、骨架屏

关键要点

  • 始终提供 alt 属性,提升可访问性
  • 使用现代图片格式(WebP、AVIF)配合传统格式作为后备
  • 响应式图片使用 srcsetsizes<picture> 元素
  • 非关键图片使用 loading="lazy" 延迟加载
  • 设置图片尺寸避免布局偏移(CLS)
  • 视频和音频提供多格式支持以确保兼容性

掌握这些知识后,你可以在网站中高效地使用图片和多媒体内容,同时保持良好的性能和用户体验。