user-select: none 在 iOS 或旧 Android 上无效,因 Safari ≤16.4、Chrome ≤61 等仅识别 -webkit-user-select 等私有前缀;需按顺序声明全部四类前缀并补 -webkit-touch-callout: none 才能彻底禁用选中与长按菜单。

为什么只写 user-select: none 在 iOS 或旧 Android 上无效
因为 Safari ≤16.4、部分 Android WebView(如 Chrome ≤61)、Firefox for Android 旧版本等,根本不识别无前缀的标准写法。它们只认私有属性:-webkit-user-select、-moz-user-select、-ms-user-select。单独依赖标准语法,等于在这些环境里完全没设防。
典型现象是:iOS 上长按或双击仍弹出“复制/翻译”菜单,Android WebView 中文字照常可拖选。这不是 bug,是浏览器解析 CSS 时直接跳过了不认识的声明。
-
-webkit-user-select: none必须写,覆盖 Safari、iOS、Chrome 旧版、Edge Legacy -
-moz-user-select: none要加,尤其 Firefox for Android 和 Firefox ≤68 -
-ms-user-select: none虽已废弃,但某些 Windows Mobile 或旧 WebView 仍依赖它 - 标准
user-select: none放最后,避免被前缀规则意外覆盖
前缀顺序写错会导致 Safari 完全忽略禁选
CSS 解析是顺序覆盖的。如果把 user-select: none 写在 -webkit-user-select: none 前面,而浏览器只支持后者(比如 iOS 15.2),那它会先读到不认识的标准属性,跳过;再读到有效的 -webkit-,才生效——看似没问题。但一旦你用 PostCSS 或构建工具自动补前缀,顺序错乱就可能让 -webkit- 被后写的 user-select 覆盖(尤其当后者带 !important)。
正确顺序只有一条:从私有到标准,且严格按内核支持范围排列:
立即学习“前端免费学习笔记(深入)”;
element {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
别用自动补全插件盲目堆砌;手动写死这四行,比依赖工具更可控。
user-select: none 对 <input> 和 <textarea></textarea> 无效是设计使然
表单控件的文本选择行为由浏览器原生控制,CSS 的 user-select 层级低于其内部逻辑。哪怕父容器写了 user-select: none,<input> 里的文字照样双击可选、光标可定位。
真要限制,得组合手段:
- 对只读场景:加
readonly属性,再配user-select: none(仅起辅助视觉提示作用) - 对不可编辑区域:用
unselectable="on"(IE/Edge Legacy 有效)或pointer-events: none(但会禁掉所有交互) - 若需保留聚焦和输入,又不想用户误选,优先考虑 UX 调整——比如缩短 placeholder 文本、避免在输入框旁放易误触的说明文字
移动端长按仍呼出菜单?还得补 -webkit-touch-callout: none
user-select: none 只管“是否允许拖拽选中”,不管系统级长按行为。-webkit-touch-callout: none 才是专治 iOS 长按时弹出“复制/搜索/翻译”气泡的属性。它不控制选区,只干掉那个浮层。
注意两点:
- 这个属性只在 iOS Safari 和部分 WKWebView 中有效,Android 不需要
- 它必须加在**目标元素本身**上,不能只靠父级继承;而且要和
user-select系列一起出现,否则长按虽不弹窗,但文字仍会被高亮选中
最简防御组合就是这五句,缺一不可:
button, .no-select {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-touch-callout: none;
}
真正麻烦的从来不是写几行 CSS,而是得时刻记住:表单控件不买账、子元素不继承、移动端有两套触发路径、伪元素内容游离在规则之外——禁选不是加个样式就完事,是层层兜底。


















