只写user-select: none没用,因ios等将文本高亮与长按菜单分治:前者由user-select控制,后者需-webkit-touch-callout: none;且必须配全前缀、作用于有尺寸/可交互元素,并在x5等内核中辅以js拦截。

只写 user-select: none 为什么没用?
因为浏览器把「长按选中文本」和「长按唤出系统菜单」当成两件事处理。user-select: none 只干预前者,对 iOS 的「保存图像」、安卓的「复制图片」等系统级菜单完全不生效。尤其在 iOS 13+、Android Chrome 80+、微信 X5 内核里,单独写这行 CSS 基本等于没写。
-webkit-touch-callout: none 必须配全前缀组合才可能生效
真正起效的最小兼容组合是:
.no-longpress {
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
注意三点:
-
-webkit-touch-callout: none必须放在第一行,某些 iOS WebView 会忽略非首行声明 - 不能全局写
* { ... }—— 会干掉<input>和<textarea></textarea>的光标定位 - 这个组合只作用于
<img>或其容器,比如img.no-longpress或.image-wrapper.no-longpress
HTML 层要避开语义触发点
部分安卓浏览器(如华为、小米)会因 alt 属性或 href 存在而主动触发菜单。所以:
- 优先用
<div style="background-image: url(...)"></div>替代<img> - 若必须用
<img>,确保移除alt属性,或设为alt="" - 给
<img>加draggable="false",并补上-webkit-user-drag: none
JS 拦截要绑定到元素本身,且防误触
CSS 不足以覆盖所有定制内核(比如微信 X5),必须加 JS 兜底:
const img = document.querySelector('img');
let longPressTimer = null;
<p>img.addEventListener('touchstart', (e) => {
longPressTimer = setTimeout(() => e.preventDefault(), 600);
});</p><p>img.addEventListener('touchend', () => clearTimeout(longPressTimer));
img.addEventListener('touchmove', () => clearTimeout(longPressTimer));</p>
关键点:
- 事件监听必须绑定到
img自身,不能委托到document或body,否则滚动和输入框聚焦会异常 -
touchmove必须清除定时器,否则轻微滑动也会触发禁用逻辑 - 别用
pointer-events: none简单粗暴处理——它会让所有点击、触摸事件失效,包括你自己的跳转或预览逻辑
所有这些手段都只是提高门槛:截图、录屏、DevTools 查 network 请求或 elements 面板依然能拿到原图。真要防,得从服务端控制资源可访问性,或改用 canvas 渲染 + 动态水印。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











