coords属性不支持百分比,因HTML规范强制要求为像素整数,须用JS动态重算缩放比或改用SVG实现响应式热点。

coords 属性根本不支持百分比——浏览器会直接忽略带 % 的值(如 "10%,20%,100%,120%"),导致热点失效或错位。这不是兼容性问题,是 HTML 规范明确禁止的。
为什么 coords 不能写百分比
HTML 标准规定 coords 必须是像素整数,单位是“原始图像尺寸下的像素”,即以 img.naturalWidth 和 img.naturalHeight 为基准。它不感知 CSS 缩放、max-width 或容器约束。哪怕你把图片缩成 50×50 像素显示,coords="100,100,200,200" 依然按原图 800×600 尺寸解释,结果就是严重偏移。
常见错误现象:
- 在 Figma 或截图工具里量出“占图宽 20%”的坐标,直接填进
coords→ 点击区域完全不对 - 给
img加了width: 100%; height: auto后,热点跟着“变小”或“漂移” → 实际是坐标没变,图被缩了 - 用开发者工具检查
area.coords返回字符串含%→ 那说明 JS 已经手动拼过,但原始属性值早被浏览器丢弃
响应式 area 热点必须用 JS 动态重算
唯一可行路径:监听尺寸变化,用原始尺寸和渲染尺寸算出缩放比,再逐个重写 coords 字符串。
立即学习“前端免费学习笔记(深入)”;
关键步骤:
- 确保图片加载完成后再读取尺寸,优先用
img.onload,而不是DOMContentLoaded;否则naturalWidth可能为 0 - 用
img.naturalWidth / img.naturalHeight获取原始尺寸 - 用
img.offsetWidth / img.offsetHeight获取当前渲染尺寸(注意:需确保图片已 layout,避免被display: none或未插入 DOM 干扰) - 计算缩放比:
scaleX = offsetWidth / naturalWidth,scaleY = offsetHeight / naturalHeight - 对每个
area的coords字符串做解析:split(',').map(Number)→ 按奇偶索引分别乘scaleX/scaleY→Math.round()→join(',')
多边形要特别小心:coords 是严格顺序的点列(x1,y1,x2,y2,...),缩放时必须保持偶数长度,且不能交换 x/y 位置,否则形状翻转。
更稳的替代方案:改用 SVG
用 SVG 替代 area + map 是多数场景的真正解法,不是“升级”,而是绕开规范限制。
优势很实在:
-
<rect x="10%" y="20%" width="20%" height="15%">这种写法原生有效,无需 JS -
viewBox自动适配任意容器宽高比,preserveAspectRatio控制缩放行为 - 支持 CSS 媒体查询,比如
@media (max-width: 768px) { .province { opacity: 0.7; } } - 点击事件可直接绑定在
<rect>上,event.target就是具体区域,不用手动判断坐标
容易被忽略的细节:
- 如果原图是 PNG/JPEG,需用
<image href="map.png" ...>嵌入 SVG,别用background-image - 导出坐标时仍要基于原始图像尺寸,但之后所有计算交给 SVG 引擎,你只管写百分比
- 高 DPR 屏幕(如 Retina)下,SVG 渲染清晰度远高于缩放后的
img+area
真正麻烦的从来不是“怎么写百分比”,而是“为什么非得写百分比”——因为图在缩放。而 area 的设计前提就是静态像素坐标。想硬撑响应式,就得自己扛缩放逻辑;想省事又可靠,就换 SVG。这两条路没有中间态。



















