coords定位不准是因浏览器不重算像素值,svg通过viewbox天然支持响应式缩放,热区坐标自动适配;必须用map时需js动态重算并校验缩放比与物理尺寸。

coords 定位不准不是你填错了,是它天生就不支持响应式——浏览器压根不重算这些像素值。
为什么coords在响应式下必然偏移
coords 绑定的是图片的 naturalWidth 和 naturalHeight,也就是文件原始尺寸。只要用了 max-width: 100%、width: 50%、Flex/Grid 拉伸,或者任何非固定 CSS 尺寸,渲染尺寸就和 natural 尺寸不一致。浏览器不会自动把 coords="100,200,300,400" 换算成当前显示尺寸下的坐标——这不是 bug,是规范如此。
常见现象包括:热区“飘”到图片外、移动端点击完全失准、缩放后只有左上角一小块能点中。
用<svg></svg>替代<map></map>是最省心的方案
SVG 的 viewBox 天然支持比例缩放,所有坐标(<rect></rect>、<circle></circle>、<polygon></polygon>)都会随容器自动适配,无需 JS 干预。
- 把原图作为
<image href="..."></image>嵌入<svg></svg>,viewBox="0 0 [w] [h]"填原始宽高 - 热区用
<a></a>包裹,支持href、target、aria-label,无障碍和 SEO 友好 - CSS 只需设
width: 100%; height: auto;,不用管coords缩放逻辑 - 导出坐标时仍按原始图尺寸写(比如
x="120"),viewBox会自动映射
示例片段:
<svg viewbox="0 0 1200 800" width="100%" height="auto"><image href="map.jpg" width="1200" height="800"></image><a href="/area1"><rect x="100" y="200" width="150" height="80"></rect></a> <a href="/area2"><circle cx="800" cy="300" r="60"></circle></a> </svg>
必须用<map></map>时,JS 动态重算的硬性条件
如果 CMS 或 legacy 系统强制要求 <map></map>,JS 重算可行但极易翻车,以下四点缺一不可:
- 必须同时监听
img.addEventListener('load', update)和window.addEventListener('resize', update);只绑resize会导致懒加载图片初始热区错位 - 每次执行前检查
img.naturalWidth > 0,否则naturalWidth为 0,缩放比变成NaN -
shape="circle"的半径也要缩放(不是只缩cx/cy),否则小图上圆会撑满整个区域 - 移动端物理尺寸建议 ≥ 44×44px,换算后要校验:比如原始图 1200×800,显示宽 360px,则横向缩放比为
360 / 1200 = 0.3,coords="500,300,50"→"150,90,15"
纯 CSS 覆盖层适合简单矩形热区
热区少、形状规则(如按钮式区域)时,<div> + 百分比定位比 JS 更轻量、更稳定。
<ul>
<li>父容器设 <code>position: relative,<img> 设 pointer-events: none
<button></button> 或 <div> 绝对定位,坐标用百分比:<code>top: 25%; left: 30%; width: 15%; height: 10%
aspect-ratio: [w] / [h] 保形,防止拉伸变形touch-action: manipulation,避免 iOS Safari 忽略小区域点击注意:coords 本身无法自适应,所谓“自适应缩放”本质是绕过它——要么换技术栈(SVG),要么换实现思路(CSS 覆盖或 JS 重算)。最常被忽略的,是忘记校验缩放后热区的物理尺寸是否满足可点击最小阈值。











