usemap与map的name必须逐字节完全匹配(含#、大小写、连字符),否则热区静默失效;coords基于naturalwidth/naturalheight,css缩放需js动态重算或改用svg。

usemap 与 map 的 name 必须逐字节匹配,否则热区静默失效
浏览器对 usemap 和 <map name></map> 的匹配极其严格:漏掉 #、大小写不一致、下划线/连字符混用、多一个空格,都会导致整个 <map></map> 被忽略。这不是 bug,是规范行为——控制台不会报错,点击也毫无反应。
常见错误示例:
-
usemap="product-map"❌(缺#)→ 应写为usemap="#product-map" -
<map name="Product-Map"></map>❌(P大写)→ 必须和usemap="#product-map"完全一致 -
<map name="product_map"></map>❌(下划线)→ 连字符-和下划线_不等价
调试时不要肉眼比对,直接复制 usemap 值粘贴到 <map></map> 的 name 属性中。
coords 坐标永远绑定 naturalWidth/naturalHeight,CSS 缩放不触发重映射
area 的 coords 是基于图片原始像素尺寸(img.naturalWidth/img.naturalHeight)定义的,不是渲染后尺寸。只要用了 width: 100%、max-width: 100%、object-fit 或任何 CSS 缩放,热区就立刻偏移——这不是取点不准,是机制如此。
例如原始图 1200×800,coords="0,0,100,100" 在桌面显示正常;缩放到 375px 宽后,该区域实际只占屏幕约 31×21px,远低于触控最小推荐尺寸 44×44px。
注意:transform: scale()、zoom、object-fit 都无法修正 coords,它们只影响视觉渲染,不改变坐标系。
响应式下必须 JS 动态重算 coords,且需监听 load 和 resize
纯 HTML/CSS 无解。唯一可靠做法是用 JS 监听 img.load 和 window.resize,在回调中按缩放比重设每个 area.coords。
关键实操点:
- 获取原始宽高:用
img.naturalWidth/img.naturalHeight,不能用img.width或clientWidth - 计算缩放比:用
img.offsetWidth / img.naturalWidth(横纵可不同,尤其object-fit: cover场景) - 遍历
area时需按shape类型解析coords: •rect→ 4 个数,x1,y1,x2,y2,需分别乘比例 •circle→ 3 个数,cx,cy,r,半径r也要缩放 •poly→ 偶数个数,成对处理,每对x,y单独缩放 - 避免重复绑定:用
img.addEventListener('load', handler, { once: true })防止多次触发
更稳妥的替代方案是 SVG,而非硬扛 map + area
如果项目已响应式、或需支持移动端触控、悬停反馈、无障碍访问,<svg></svg> 是目前最可控的现代解法。
核心优势:
-
<svg viewbox="0 0 [origW] [origH]"></svg>中填原始尺寸,内部所有坐标(<rect x="10%"></rect>、<path d="M10,20..."></path>)天然随视口缩放 - 无需 JS 补偿,
aria-label、tabindex、focusable="true"原生支持 - 复杂多边形热区维护成本更低,导出工具(如 Figma 插件)可批量转百分比坐标
代价是不能直接复用 PS 导出的像素坐标,需做一次换算:x% = (x_px / naturalW) * 100。但比起 JS 动态重算的兼容性坑(比如 <picture></picture> 切换 srcset 时 naturalWidth 异步变化),这个成本低得多。
真正容易被忽略的是:当图片通过 <picture></picture> 或 srcset 切换不同分辨率源时,naturalWidth 可能异步变化,而 JS 重算逻辑若没绑定到最终加载的 <img> 实例上,就会用错原始尺寸——这种问题只在真机切屏时暴露,桌面调试完全看不出来。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











