图片与多媒体
图片和多媒体内容是现代网页的重要组成部分,它们极大地丰富了用户体验。HTML5 提供了强大的图片和多媒体支持,包括响应式图片、矢量图形、音频视频等。本文档将详细介绍如何使用这些元素以及相关的性能优化技巧。
1. 图片基础 - <img> 元素
1.1 基本用法
<img> 元素用于在页面中嵌入图片,是一个自闭合标签(void element)。
1
| <img src="image.jpg" alt="图片描述">
|
必需属性:
推荐属性:
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="照片">
<img src="https://www.example.com/images/photo.jpg" alt="照片">
<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="">
<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;">
<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
| <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 属性(响应式图片)
srcset 和 sizes 属性用于实现响应式图片,根据设备像素密度和屏幕宽度选择最合适的图片。
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 ">
|
实际工作流程:
- 浏览器读取
sizes 属性,确定图片在页面上的显示宽度
- 根据设备像素比(DPR)计算需要的实际像素宽度
- 从
srcset 中选择最接近且大于所需尺寸的图片
- 下载并显示选中的图片
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
| <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>
<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>
|
工作原理:
- 浏览器从上到下检查每个
<source> 的 media 条件
- 选择第一个匹配条件的
<source>
- 如果没有匹配的
<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> <source srcset="photo.avif" type="image/avif"> <source srcset="photo.webp" type="image/webp"> <img src="photo.jpg" alt="照片"> </picture>
|
支持的图片格式类型:
image/avif:AVIF 格式(最佳压缩比)
image/webp:WebP 格式(很好的压缩比,广泛支持)
image/apng:APNG 格式(动画 PNG)
image/png:PNG 格式
image/jpeg 或 image/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> <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 |
预加载策略 |
none、metadata、auto |
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(
.mp3,audio/mpeg):最广泛支持
- OGG(
.ogg,audio/ogg):开源格式
- WAV(
.wav,audio/wav):无损,文件较大
- AAC(
.aac,audio/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 |
预加载策略 |
none、metadata、auto |
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(
.mp4,video/mp4):H.264 编码,最广泛支持
- WebM(
.webm,video/webm):VP8/VP9 编码,开源,文件较小
- OGG(
.ogv,video/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%; 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
| <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
| <img src="icon.svg" alt="图标">
<picture> <source srcset="icon.webp" type="image/webp"> <img src="icon.png" alt="图标"> </picture>
|
需要透明的图片
1 2 3 4 5
| <picture> <source srcset="logo.webp" type="image/webp"> <img src="logo.png" alt="Logo"> </picture>
|
6.3 图片优化技巧
1. 选择合适的尺寸
1 2 3 4 5 6
|
<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
| <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
| <img src="hero-image.webp" alt="首屏图片" fetchpriority="high" loading="eager" width="1200" height="600">
<img src="content-image.jpg" alt="内容图片" width="800" height="600" style="width: 100%; height: auto;">
<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 中图片和多媒体的使用:
<img> 元素:基础用法、alt/title、srcset/sizes、懒加载等
- SVG 矢量图形:内联使用、图标系统、样式控制
<picture> 响应式图片:格式选择、屏幕适配
<audio> 音频:基本用法、自定义控制
<video> 视频:基本用法、响应式、自定义控制栏
- 性能优化:格式选择、懒加载、占位符、骨架屏
关键要点:
- 始终提供
alt 属性,提升可访问性
- 使用现代图片格式(WebP、AVIF)配合传统格式作为后备
- 响应式图片使用
srcset、sizes 或 <picture> 元素
- 非关键图片使用
loading="lazy" 延迟加载
- 设置图片尺寸避免布局偏移(CLS)
- 视频和音频提供多格式支持以确保兼容性
掌握这些知识后,你可以在网站中高效地使用图片和多媒体内容,同时保持良好的性能和用户体验。