点赞 + 关注 + 收藏 = 学会了
html2canvas 简介
html2canvas 是一个纯前端的 JavaScript 库,能直接在浏览器里把 HTML 元素 “拍” 成 Canvas 图片。不用麻烦后端接口,就能实现网页截图、生成分享海报、保存页面快照等需求。
安装方法
html2canvas 支持两种常见的安装方式,根据你的项目环境选就行:
1. npm /yarn 安装(推荐)
如果你的项目用了 Webpack、Vite 等构建工具,直接用包管理器安装:
# npm 安装
npm install html2canvas
# yarn 安装
yarn add html2canvas
本文使用 Vite 创建 Vue3 项目,通过 Vue3 的语法来讲解。在其他框架使用 html2canvas 用法也是差不多的。
2. CDN 引入
如果是简单的 HTML 项目,直接在页面里引入 CDN 链接:
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
基础用法
先看一个最简单的例子:点击按钮,把指定的 div 转成 Canvas 并显示在页面上。

<template>
<div>
<!-- 要截图的区域 -->
<div ref="captureRef" style="padding: 20px; background: #f0f0f0;">
<p style="font-size: 16px; margin: 0;">随便写点什么,html2canvas 会把它变成图片~</p>
</div>
<!-- 截图按钮 -->
<button @click="handleCapture">点击截图</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
import html2canvas from 'html2canvas'
// 获取要截图的 DOM 元素
const captureRef = ref(null)
// 截图函数
const handleCapture = async () => {
// 调用 html2canvas,等待生成 Canvas
const canvas = await html2canvas(captureRef.value)
// 把 Canvas 加到页面上看看效果
document.body.appendChild(canvas)
}
</script>
这段代码看似简单,但第一个坑也出现了。
此时如果在“截图区”加多一个 h2,结果可能会出乎你所料。

<!-- 要截图的区域 -->
<div ref="captureRef" style="padding: 20px; background: #f0f0f0;">
<h2>雷猴</h2>
<p style="font-size: 16px; margin: 0;">随便写点什么,html2canvas 会把它变成图片~</p>
</div>
<h2> 标题的样式没跟着生成出来啊。。。
解决方法很简单,不使用浏览器默认样式,给所有标签都加上指定样式。

<template>
<div>
<!-- 要截图的区域 -->
<div
ref="captureRef"
class="capture-area"
style="padding: 20px; background: #f0f0f0;"
>
<!-- 关键样式建议写在行内,或者确保非 scoped -->
<h2 class="title">这是要截图的内容</h2>
<p style="font-size: 16px; margin: 0;">随便写点什么,html2canvas 会把它变成图片~</p>
</div>
<!-- 截图按钮 -->
<button @click="handleCapture">点击截图</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
import html2canvas from 'html2canvas'
// 获取要截图的 DOM 元素
const captureRef = ref(null)
// 截图函数
const handleCapture = async () => {
// 调用 html2canvas,等待生成 Canvas
const canvas = await html2canvas(captureRef.value)
// 把 Canvas 加到页面上看看效果
document.body.appendChild(canvas)
}
</script>
<style scoped>
.capture-area {
width: 400px;
box-sizing: border-box;
border: 1px solid #ccc;
}
.title {
font-size: 24px;
font-weight: bold;
margin: 0 0 10px 0;
}
</style>
常用配置选项
html2canvas 提供了很多配置项,能帮你解决各种场景问题,这里列几个最常用的:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
scale | number | window.devicePixelRatio | 缩放比例,默认用设备像素比,提高截图清晰度(设为 1 会模糊)。 |
useCORS | boolean | false | 是否允许加载跨域图片,设为 true 才能正确显示跨域图片。 |
backgroundColor | string | #ffffff | Canvas 背景色,设为 null 可以得到透明背景。 |
logging | boolean | false | 是否在控制台打印日志,调试时可以设为 true 看问题。 |
scrollX | number | 0 | 截图时的水平滚动偏移,解决页面滚动导致的内容错位。 |
scrollY | number | 0 | 截图时的垂直滚动偏移,同上。 |
如果你要截的元素包含图片,而且这张图片和你的网站存在跨域情况,大概率会出现图片出空白的情况。

<template>
<div>
<!-- 要截图的区域 -->
<div
ref="captureRef"
class="capture-area"
style="padding: 20px; background: #f0f0f0;"
>
<!-- 关键样式建议写在行内,或者确保非 scoped -->
<h2 class="title">这是要截图的内容</h2>
<img src="https://iili.io/fcR7gSe.md.png" alt="" style="width: 140px;">
<p style="font-size: 16px; margin: 0;">随便写点什么,html2canvas 会把它变成图片~</p>
</div>
<!-- 截图按钮 -->
<button @click="handleCapture">点击截图</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
import html2canvas from 'html2canvas'
// 获取要截图的 DOM 元素
const captureRef = ref(null)
// 截图函数
const handleCapture = async () => {
// 调用 html2canvas,等待生成 Canvas
const canvas = await html2canvas(captureRef.value)
// 把 Canvas 加到页面上看看效果
document.body.appendChild(canvas)
}
</script>
<style scoped>
.capture-area {
width: 400px;
box-sizing: border-box;
border: 1px solid #ccc;
}
.title {
font-size: 24px;
font-weight: bold;
margin: 0 0 10px 0;
}
</style>
要解决这个问题需要2步操作。
- 图片服务器配置
Access-Control-Allow-Origin: *(允许跨域) - html2canvas 配置
useCORS: true
如果想更稳妥一点,还可以给图片标签加 crossorigin="anonymous" 属性。
iili.io 这个图床是允许跨域的,所以我们直接在 html2canvas 里配置 useCORS: true 即可。

// 省略部分代码
const canvas = await html2canvas(captureRef.value, {
useCORS: true
})
高级用法:导出并下载图片
生成 Canvas 后,通常需要把它转成图片文件让用户下载,这里用 toDataURL 实现

<template>
<div>
<!-- 要截图的区域 -->
<div
ref="captureRef"
class="capture-area"
style="padding: 20px; background: #f0f0f0;"
>
<!-- 关键样式建议写在行内,或者确保非 scoped -->
<h2 class="title">这是要截图的内容</h2>
<img src="https://iili.io/fcR7gSe.md.png" alt="" style="width: 140px;">
<p style="font-size: 16px; margin: 0;">随便写点什么,html2canvas 会把它变成图片~</p>
</div>
<!-- 截图按钮 -->
<button @click="handleCapture">点击截图</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
import html2canvas from 'html2canvas'
// 获取要截图的 DOM 元素
const captureRef = ref(null)
// 截图函数
const handleCapture = async () => {
// 调用 html2canvas,等待生成 Canvas
const canvas = await html2canvas(captureRef.value, { useCORS: true });
// 1. 把 Canvas 转成 PNG 格式的 base64 数据
const imgData = canvas.toDataURL('image/png');
// 2. 创建下载链接
const link = document.createElement('a');
link.download = '我的截图.png'; // 下载的文件名
link.href = imgData;
// 3. 触发点击下载
link.click();
}
</script>
<style scoped>
.capture-area {
width: 400px;
box-sizing: border-box;
border: 1px solid #ccc;
}
.title {
font-size: 24px;
font-weight: bold;
margin: 0 0 10px 0;
}
</style>
常见坑点及避坑指南
html2canvas 虽然好用,但坑也不少。
跨域图片不显示或报错
前面已经提到了,如果截图里有跨域图片(比如图床的图),默认会显示空白。原因是浏览器的同源策略限制,html2canvas 无法直接读取跨域图片的像素。
解决方法:
- 图片服务器配置
Access-Control-Allow-Origin: *(允许跨域) - 给图片标签加
crossorigin="anonymous"属性 - html2canvas 配置
useCORS: true
<!-- 图片标签加 crossorigin -->
<img src="https://example.com/image.jpg" crossorigin="anonymous">
CSS 样式显示异常
部分 CSS 属性(如 transform、box-shadow、复杂渐变、伪元素 ::before/::after)可能渲染不对,甚至完全不显示。
html2canvas 是通过解析 DOM 和 CSS 手动绘制 Canvas 的,不是所有 CSS 都支持。
解决方法:
- 尽量用简单的 CSS 布局,避免太复杂的特效
- 把复杂样式(如渐变、阴影)转成图片代替
- 查看官方文档的 CSS 支持列表,避开不支持的属性
自定义字体渲染失败
用了自定义字体(如 @font-face),截图里却变成了默认字体。
html2canvas 截图时,字体可能还没加载完,就用了默认字体渲染。
解决方法:
- 等待字体加载完成后再截图,用
document.fonts.ready即可
document.getElementById('btn').addEventListener('click', async () => {
// 等待所有字体加载完成
await document.fonts.ready;
const element = document.getElementById('capture');
const canvas = await html2canvas(element);
document.body.appendChild(canvas);
});
滚动条导致截图不全或有滚动条
如果要截图的元素有滚动条,截图会包含滚动条,或者内容被截断。
解决方法:
- 截图前先隐藏滚动条,截图后恢复
const element = document.getElementById('capture');
// 保存原来的 overflow 样式
const originalOverflow = element.style.overflow;
// 隐藏滚动条
element.style.overflow = 'hidden';
const canvas = await html2canvas(element, {
scrollX: 0,
scrollY: 0 // 重置滚动偏移
});
// 恢复原来的样式
element.style.overflow = originalOverflow;
iframe 内容无法捕获
如果页面里有 iframe,html2canvas 无法截图 iframe 里的内容。
同源策略限制,无法直接访问 iframe 内部的 DOM。
解决方法:
- 如果 iframe 和主页面同域,可以手动获取 iframe 里的元素再截图
- 如果跨域,基本无解,建议换其他方案(比如后端截图)
页面元素太多导致性能差
截图区域元素多、图片大时,生成 Canvas 会很慢,甚至浏览器卡顿。
解决方法:
- 适当降低
scale(比如设为 1.5 而不是 2) - 截图前隐藏不必要的元素(比如
display: none) - 只截图需要的部分,不要截整个页面
SVG 元素显示异常
直接截图 SVG 可能会变形、错位,甚至不显示。
解决方法:
- 先把 SVG 转成图片,再插入 DOM 截图。可以用
canvg库辅助转换,或者手动把 SVG 转成 base64 图片
// 简单的 SVG 转图片示例
const svgElement = document.querySelector('svg');
const svgData = new XMLSerializer().serializeToString(svgElement);
const img = new Image();
img.src = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgData)));
// 等图片加载完后,替换原来的 SVG,再截图
img.onload = async () => {
svgElement.parentNode.replaceChild(img, svgElement);
const canvas = await html2canvas(element);
document.body.appendChild(canvas);
};
z-index 层级错乱
截图里的元素层级和实际页面不一样,该在上面的元素跑到下面了。
html2canvas 对 z-index 的解析有时会出问题,尤其是元素没有显式设置 position 时。
解决方法:
- 给需要层级的元素显式设置
position(如relative、absolute) - 调整 DOM 顺序(后面的元素会覆盖前面的),代替
z-index
点赞 + 关注 + 收藏 = 学会了