
简介这是一份CSS cursor属性可选值的中英文对照速查文档面向Web前端初学者及需要精细控制鼠标交互的开发人员帮助解决游标取值类型多、语义易混淆、不确定何时选用哪个值的问题。资源为单个PDF文件压缩包大小仅40KB内容轻巧便携已有742人学习下载。文档系统整理了crosshair十字准心、pointer手形、wait等待、help帮助、text文本编辑、move移动、八方向resize拉伸、no-drop禁止释放、progress处理中、default默认及自定义url等常用取值并为每个值提供了视觉形态描述、中文注释和适用场景例如绘图工具中利用十字准线精确定位、链接上呈现手形提示可点击、后台任务进行时显示沙漏等待。同时补充了关键兼容性细节如早期IE5需用hand替代pointer、自定义光标文件须为.cur或.ani格式、在自定义url后要附带通用cursor作为后备避免因格式或兼容问题导致光标失效。通过这份归纳清晰的速查文档读者能快速建立对cursor属性的系统认识在实际项目中准确选择鼠标形态优化页面交互细节与可用性适合前端日常开发、参考查阅或教学复习。1. cursor 不是只有 pointer先搞清 CSS 光标样式的真实边界写页面的人第一次意识到 cursor 的威力通常是在做画板或拖拽组件的时候鼠标对准一个小手柄怎么都差一像素光标明明切成了 move拖起来却总觉得自己按偏了。CSS 的 cursor 属性负责告诉浏览器「当前指针落在什么操作语义上」它由几十个关键字、一条自定义图片链和两个热点坐标组成复杂度比多数人印象里的「pointer 就是手型」要高一截。下面按关键字取值、自定义光标、鼠标移入事件下的动态切换、以及调试时最该调的 4 个参数四条线展开适合写富文本、画布工具、可拖拽面板的前端也适合想把禁用态、缩放态做细的样式开发者。读完之后你能回答三个问题浏览器默认光标是谁决定的、自定义光标为什么总偏、以及线上环境验证光标的正确姿势。2. CSS cursor 关键字全表20 多个取值背后的浏览器行为cursor 的可选值从用途上分成四组形状类、手势类、编辑与状态类、缩放类。理解分组比背列表重要因为同一个关键字在实际布局里的表现细节差异很大。比如 wait 和 progress 都能显示忙碌动画但 wait 表示「别点界面卡死」progress 表示「可以点后台在跑」再比如 not-allowed 只改视觉并不拦截点击。这一章先把浏览器的默认决策机制讲清楚再给出一张可以直接抄的取值表最后落到 CSS 选择器和继承规律上这是排查「光标为什么不生效」的第一站。2.1 auto 与 default谁替浏览器做决定最容易混的一对是 auto 和 default。default 无条件画一个普通箭头浏览器不替你做任何决策auto 则把决定权交还给浏览器的用户代理样式——链接上变手型、输入框里变 I 型、带 title 的元素上变问号、页面阻塞时变忙碌。换句话说default 是「强制」auto 是「放权」。/* 常见但冗余浏览器对 a、button 本身就按 auto 给出手型 */ a, button { cursor: pointer; } /* 需要强制统一视觉时才这样写比如自定义按钮组件 */ .btn-custom { cursor: pointer; }写自定义 Button 组件时把 cursor: pointer 加上是合理的因为用了 div 加 rolebutton 的假按钮UA 不会自动给手型。原生 a 和 button 上过度写 pointer 反而会覆盖掉浏览器在禁用态disabled button 在某些内核下显示 not-allowed的智能行为。2.2 主流取值速查与适用场景关键字视觉反馈适用场景auto由 UA 决定默认值链接、输入框交给浏览器default普通箭头一般内容撤销所有手势提示pointer手型可点击元素、自定义按钮text / vertical-textI 型竖/横输入框、contenteditable区域crosshair十字线画布、截图框选、图像编辑器move / grab / grabbing移动/抓取/抓取中面板拖动、拖拽条目not-allowed / no-drop禁止/禁止放置禁用状态、非法拖拽目标wait / progress忙/后台忙同步阻塞、异步任务help问号带帮助说明的控件cell / copy单元格/复制表格选取、拖拽复制context-menu箭头加菜单右键菜单入口alias快捷方式箭头拖拽创建链接、快捷方式row-resize / col-resize / n-resize 系列方向箭头调整尺寸、分栏拖动zoom-in / zoom-out放大镜内加减号图片预览、画布缩放none隐藏光标全屏游戏、绘图演示低频值里要单独留意 zoom-in 和 zoom-out它们在部分老内核的桌面浏览器上不生效移动端 Safari 对部分手势类取值支持也不一致。写之前查一下目标浏览器版本没坏处尤其是给企业内部老浏览器做兼容的时候建议实测而不是直接抄文档。2.3 用 CSS 选择器和继承规律控制光标cursor 是一个可继承属性这点容易被忽略父容器设了 not-allowed所有子元素一起跟着变除非子元素自己显式覆盖。反过来一个列表容器上设了 pointer整块区域的空白地方也会变成手型用户会误以为处处可点。常见的正确做法是把光标绑定在真正交互的元素上而不是容器上/* 禁用按钮视觉上禁止点击拦截交给 disabled 逻辑 */ .btn[disabled] { cursor: not-allowed; pointer-events: auto; /* 确认没有全局样式把它关掉 */ } /* 拖拽条目悬停显示抓取按下瞬间切到抓取中 */ .drag-item { cursor: grab; } .drag-item:active { cursor: grabbing; } /* 可编辑区域强制文本光标覆盖继承来的手型 */ [contenteditabletrue] { cursor: text; }这里的逻辑是:active优先级高于非伪类状态所以按下立刻换光标disabled 属性配合属性选择器不需要额外类名。要注意 not-allowed 不拦截点击真正禁止操作要靠 disabled 属性、aria-disabled 或 JS 逻辑样式层别替交互层做决定。触屏设备上 :hover 有「粘滞」现象点一下会一直保持悬停态所以光标相关的状态切换不要作为唯一反馈还要配合 active 或视觉底色变化。3. 自定义光标用 url() 与 SVG data URI 接管 CSS cursor关键字无法满足品牌化需求时就要用自定义图片。这一节讲三件事完整语法怎么写、热点坐标为什么必须显式给、以及如何用 SVG data URI 把光标图片内联进 CSS省掉请求也绕开跨域问题。自定义光标的兼容性坑比关键字多生产环境里「看着没变」八成是 fallback 链或坐标写错下面每一步都给出可复现的写法。3.1 完整语法与 fallback 链的书写规则自定义光标的语法是一条链一个或多个 url()最后必须跟一个关键字兜底。浏览器按顺序尝试加载图片全失败就用最后的关键字。.custom-cursor { cursor: url(pick.cur) 8 8, url(pick.svg) 8 8, pointer; }三个要点第一最后一个 token 必须是关键字不能以 url() 结尾否则整条声明按无效处理浏览器直接退回默认箭头第二多个 url() 的意义是兼容性降级老内核吃 .cur现代浏览器吃 .svg谁先加载成功用谁第三url() 后面的两个数字是热点坐标后面单独讲。检查一条自定义光标是否合法最快的办法是在 DevTools 的 Computed 面板看 cursor 的最终解析值如果只剩兜底关键字说明图片链出问题了。提示cursor 自定义图片的加载是异步的图片没到位之前先显示兜底光标。首屏立即要生效的光标建议用 data URI 内联或者提前预加载避免用户看到箭头闪一下再变成自定义样式。3.2 热点坐标默认 0,0 导致瞄准偏差热点坐标hot spot是图片上真正对应鼠标指针位置的那个点。不写默认是图片左上角 (0, 0)对箭头类光标无所谓但十字准星、画笔这类依赖精确瞄准的光标会明显偏位。32×32 的准星图中心在 (16, 16).crosshair-cursor { cursor: url(aim.svg) 16 16, crosshair; }常见错误是按「图片视觉中心」凭感觉填数字。正确做法是在 PS 或设计稿里量出瞄准点相对图片左上角的像素坐标再填进 CSS。坐标单位是图片自身像素不是 CSS 像素Retina 下如果提供的是 64×64 资源热点坐标要按 64 的实际像素算而不是按显示尺寸折半。画板工具我一般把热点做成一个十字辅助线叠加到原图上确认视觉中心与坐标一致再导出。3.3 用 SVG data URI 免去图片文件请求自定义光标最省事的现代方案是直接内联 SVG不产生额外请求也不怕路径配置错误。SVG 里可以直接画任意形状配合透明度做空心或实心光标.cursor-copy { cursor: url(data:image/svgxml;utf8,%3Csvg xmlns%22http://www.w3.org/2000/svg%22 width%2224%22 height%2224%22%3E%3Cpath d%22M3 3h10v10H3z%22 fill%22none%22 stroke%22black%22 stroke-width%222%22/%3E%3C/svg%3E) 3 3, copy; }直接写在 CSS 里的 SVG 必须做百分号编码换成%3C双引号换成%22#换成%23否则引号和 CSS 的 url() 冲突。手动改容易错用控制台一行生成const svg svg xmlnshttp://www.w3.org/2000/svg width24 height24path dM3 3h10v10H3z fillnone strokeblack//svg; console.log(encodeURIComponent(svg));把输出粘回 CSS 的 url() 里即可。内联之外还有一种做法是外链同源静态资源但要小心两点跨域图片在不同内核下对 cursor 的支持不一致且防盗链会导致图片加载失败后静默回退光标图片一般每个会话只加载一次但为了缓存命中建议把不常用的光标合并成少量几个文件而不是每个组件单独一张。CSScursor的加载失败不会触发明显的网络报错排错时要在 Network 面板单独看图片请求的状态码。3.4 格式与尺寸为什么老手只做 32×32浏览器对自定义光标尺寸有限制规范没有强制单像素上限但常见实现按 32×32 以内的标准渲染超出会被缩放缩放后边缘发虚热点坐标也会随缩放漂移。格式选型参考下表格式兼容性使用建议.cur / .ico老内核普遍支持需要专门工具生成维护成本高.png除极老内核外都支持首选注意透明底与边缘抗锯齿.svg现代浏览器灵活、可内联解析开销略高于位图实际项目里我通常导出一份 32×32 的 PNG再按需生成一份 SVG data URI 做增强。两张图的热点坐标保持一致否则同一套样式在不同浏览器里手指头「按的位置」不一样。4. 鼠标移入事件下的 CSS cursor 动态切换与常见陷阱理解了静止状态下的 cursor接下来处理动态切换。很多新手在 JS 里监听 mousemove 逐像素改 style.cursor结果性能没出问题倒是覆写顺序先乱了。这一章的主题是能用 CSS 选择器表达的状态切换就不要动 JS必须动 JS 时用事件委托和光标层并明确 cursor 的真实生效优先级。4.1 能用 CSS 选择器完成的光标切换鼠标移入、按下、移出这类状态CSS 的:hover、:active和属性选择器完全够用不需要 JS 参与.help-entry { cursor: help; } .help-entry:hover { background: #fff8e1; } /* 光标与底色反馈同时变 */ .drag-handle { cursor: grab; } .drag-handle:active { cursor: grabbing; }:active只作用于按下瞬间鼠标左键按住不放移动端长按也能触发所以拖拽场景的「抓取中」用:active就能覆盖大多数情况。能用选择器表达的前提是状态本身和 DOM 结构绑定比如 disabled、draggable、contenteditable如果状态存在 JS 变量里比如「正在拖拽」这个布尔值再用后面的事件方案。4.2 拖拽中用 pointermove 接管 body 级光标拖拽过程中鼠标经常甩到元素外面如果光标只挂在被拖元素上一离开元素边界就变回箭头。常见做法是把光标写到 body 上用 pointer 事件的生命周期统一管理const handle document.querySelector(.slider-thumb); let dragging false; handle.addEventListener(pointerdown, (e) { dragging true; document.body.style.cursor grabbing; // 全程生效不随鼠标离开元素而丢失 handle.setPointerCapture(e.pointerId); // 指针捕获后续事件都派发给 handle }); handle.addEventListener(pointerup, () { dragging false; document.body.style.cursor ; // 清空内联样式交还给 CSS });这里有两个关键参数。document.body.style.cursor是内联样式优先级高于普通 CSS 规则拖拽期间全局光标稳定结束时置成空字符串恢复继承链。setPointerCapture(e.pointerId)保证鼠标哪怕移出窗口pointerup 也会派发到 handle 上否则松开鼠标的场景可能漏掉重置逻辑。用 pointer 事件族而不是 mouse 事件族是因为它同时覆盖鼠标、触控笔和触摸且支持指针捕获。cursor 内联样式覆盖优先级可以按这个顺序记忆UA 默认 继承值 普通规则 :hover等伪类 内联样式 !important。排查「为什么改了没反应」时先按这个链路倒着查一遍。4.3 事件委托与白名单校验在复杂页面上每个可交互元素各自监听指针事件改光标既浪费监听器数量又容易出现状态交叉。常见做法是 document 级委托把「该显示什么光标」收敛成一份数据const ALLOWED new Set([pointer, text, move, not-allowed, help, crosshair, grabbing]); document.addEventListener(pointermove, (e) { const el e.target.closest([data-cursor]); const next el ? el.dataset.cursor : ; document.body.style.cursor ALLOWED.has(next) ? next : ; // 白名单兜底 }, { passive: true });closest([data-cursor])从事件目标往上找最近带>.cursor-layer { position: fixed; inset: 0; pointer-events: none; /* 鼠标事件穿透点到哪都是底下的元素 */ cursor: url(brush.svg) 8 8, none; /* none 兜底图片失败时隐藏光标而不是显示箭头 */ transform: translate(-100px, -100px); /* 初始移出屏幕等 JS 给坐标 */ }光标层的移动由 JS 在 pointermove 里写 transform层本身不接收任何鼠标事件所以不会和底层画布的交互冲突。注意两个 cursor 控制不了的角落原生滚动条上的光标由 UA 管理页面样式覆盖不到iframe 内部的光标由 iframe 文档自己的 CSS 决定外层页面的 cursor 链进不去。做整站统一光标时这两处是漏网之鱼。5. cursor 调试的 4 个必调参数与快速验证技巧遇到「光标没变」先别怀疑浏览器有病按下面 4 个参数自查一遍绝大多数问题十分钟内能定位。5.1 四参数自查表参数常见坑检查方式热点坐标默认 0,0 导致瞄准偏差用带中心十字的图片叠加验证图片尺寸大图被浏览器缩放失真重新导出 32×32 位图或等比例 SVGfallback 关键字忘写或写在 url() 前面整条声明无效DevTools Computed 面板看最终解析值覆写顺序父级继承、伪类、内联样式覆盖按「内联 伪类 普通规则 继承」倒查5.2 快速验证脚本想知道当前浏览器支持哪些关键字、哪些链路有效用一段探测脚本点击循环即可const VALUE_LIST [auto, default, pointer, text, move, not-allowed, wait, help, crosshair, grab, grabbing, copy, cell, zoom-in, none]; let idx 0; const probe document.getElementById(probe-box); probe.addEventListener(click, () { probe.style.cursor VALUE_LIST[idx]; // 打印两个值设置进去的原始值和浏览器解析后的最终值 console.log(设置:, VALUE_LIST[idx], | 解析:, getComputedStyle(probe).cursor); idx (idx 1) % VALUE_LIST.length; });浏览器不会对 cursor 关键字报语法错误写错值只会静默回退到 autogetComputedStyle读到的解析值能直接区分「这个值被接受了」和「被回退了」。none 放到列表最后一位因为隐藏光标会让自己失去视觉反馈点完再点一下能恢复。5.3 自定义光标加载失败的两种验证法自定义光标加载失败是静默行为不会在 Console 里报错。第一个验证法是临时篡改兜底关键字把cursor: url(pick.svg) 8 8, crosshair的兜底临时改成move如果此时光标从箭头变成了移动符号说明图片没加载成功图片请求本身有问题如果还是箭头说明整条声明没被解析问题在语法。第二个验证法是在 Network 面板过滤图片类型确认 url() 对应的文件请求是否发出、状态码是否 200、响应体是否是合法图片格式。过滤器写mime:image能看到光标图片的真实请求结果而不是猜测浏览器有没有去取。两种方法配合语法问题和网络问题一测便知。本文还有配套的精品资源点击获取