Firefox 不认 PNG 光标,应优先使用 .cur 文件;.cur 原生支持热点且全浏览器兼容,PNG 需 RGBA 格式、≤32×32px、显式坐标,否则 Firefox 显示灰色方块或退为箭头。

Firefox 不认 PNG 光标?优先用 .cur 文件
Firefox 对 cursor: url() 的图片格式最挑剔:它基本只认 .cur,对 PNG 要求 RGBA + ≤32×32px + 显式热点坐标,稍有不符就显示灰色方块或直接退成箭头。Chrome 和 Safari 宽松些,但也不保证 64×64 以上 PNG 能正常渲染。
正确做法是把设计稿里的光标导出为 .cur 格式,用专业工具(如 RealWorld Cursor Editor 或在线 converter)生成,确保包含热点(hotspot)坐标。不要依赖 PS 导出 PNG 后直接丢进 url()——那只是看起来“能跑”,上线后 Firefox 用户大概率看到默认箭头。
-
.cur原生支持热点,无需额外写坐标(除非你要偏移) - 同一张图导出
.cur和.png两份,用多 URL 回退链兜底 - 避免用
.svg:Safari 支持有限,iOS Safari 完全不认,且外部引用在 Firefox 中被拦截
Chrome/Safari 加载失败?检查尺寸与 Alpha 通道
即使你用了 PNG,也常因两个隐形条件失败:cursor 要求图像必须是带完整 Alpha 通道的 RGBA 模式,不能是索引色(Indexed)或 RGB;尺寸建议严格控制在 32×32px 以内——128×128 在 Chrome 可能被缩放失真,macOS 上甚至直接降级为系统默认光标。
用 macOS 预览或 Windows 照片查看器打开 PNG,右键「显示简介」确认尺寸和色彩模式;在 Photoshop 中导出时选「存储为 Web 所用格式(旧版)」并勾选「透明度」,禁用「仿色」和「颜色表」。
立即学习“前端免费学习笔记(深入)”;
- 导出后用
file cursor.png命令检查是否含 alpha:Color space: sRGB, Alpha: yes才合格 - 尺寸超限不会报错,但 DevTools 里 hover 到
cursor属性时,值会显示 strikethrough(表示被浏览器忽略) - 不要信「导出为 PNG-24」这种模糊说法,必须验证实际文件属性
路径 404 却没报错?路径必须相对 CSS 文件位置
浏览器加载 url() 时,路径解析基准是 CSS 文件所在目录,不是 HTML 页面路径。写成 ../icons/hand.png 很容易在嵌套路由或构建后失效,而控制台通常不报 404——因为浏览器静默跳过整条 cursor 规则,而非仅忽略图片。
推荐统一用根相对路径:/assets/cursors/hand.cur,或内联 base64(适合小图标):url("data:image/x-icon;base64,...")。后者绕过跨域和路径问题,但体积增大,且 base64 字符串需确保无换行、空格。
- 双击打开
index.html时走file://协议,Chrome/Edge 会直接阻止url()加载本地图片——必须起 HTTP 服务验证 - CDN 场景下,确保图片响应头是
Content-Type: image/x-icon(.cur)或image/png(PNG),不是text/plain - 用
curl -I https://yoursite.com/assets/cursors/hand.cur确认返回状态码和 header
为什么加了 fallback 还是显示箭头?fallback 关键字必须合法
写了 cursor: url(x.cur), auto; 却仍看到默认箭头,大概率是 fallback 关键字拼错或不被支持。浏览器对 fallback 值大小写敏感,且只接受标准关键字:auto、default、pointer、text、move、not-allowed 等。写成 "hand"、"grab" 或 "Pointer" 都无效,整条声明会被忽略。
更隐蔽的问题是:某些 UI 框架(如 Ant Design)或重置样式(normalize.css)会在全局设 * { cursor: default },导致你的规则被更高权重覆盖。DevTools 里看 cursor 是否被 strikethrough 是最快判断方式。
- fallback 必须是规范关键字,不能是自定义类名或变量
- 多个 url 回退链中,每个
url()后都得跟一个合法 fallback,例如:cursor: url(bad.cur), url(fallback.png) 0 0, pointer; - 移动端要主动关闭:
@media (pointer: coarse) { * { cursor: auto !important; } },否则光标逻辑干扰触摸体验
真正卡住人的不是“怎么写”,而是“为什么写了却没反应”——浏览器对 cursor: url() 的静默失败机制太强,它不报错、不警告,只悄悄跳过整条规则。验证时务必在真实 HTTP 环境下,用 DevTools 检查 computed 样式是否生效,而不是仅靠肉眼观察。


















