使用CSS,可以防止用户使用user-select: none ,在一个元素中选择文本。现在,可以理解为什么这样做可能被认为是 "有争议的"。我的意思是,我们应该禁用标准的用户行为吗?一般来说,不,我们不应该这样做。但是,禁用文本选择是否有一些合法的(尽管是罕见的)使用情况?我认为是的。
在这篇文章中,我们将探讨这些用例,并看看我们如何使用user-select: none 来改善(而不是阻碍)用户体验。还有一点值得注意的是,这个 user-select属性除了none ,还有其他值可以用来改变文本选择的行为,而不是完全禁用它,还有一个值甚至可以强制执行文本选择,所以我们也会看看这些。
可能的user-select 值
让我们通过不同的user-select 值和它们的作用来开始吧。
对一个元素应用user-select: none; ,意味着它的文本内容和嵌套的文本内容在功能上不能选择,在视觉上也不能选择(也就是说,::selection 不能工作)。如果你要做一个包含一些不可选择的内容的选择,不可选择的内容将从选择中省略,所以它实现得相当好。而且支持度很高。
这个浏览器支持数据来自Caniuse,它有更多细节。一个数字表示该浏览器在该版本及以上版本支持该功能。
桌面浏览器
| 浏览器 | 火狐 | IE | 边缘浏览器 | 浏览器 |
|---|---|---|---|---|
| 4 | 2 | 10 | 12 | 3.1 |
手机/平板电脑
| 安卓浏览器 | 安卓火狐 | 安卓 | iOS Safari |
|---|---|---|---|
| 105 | 104 | 2.1* | 3.2* |
不利的是,user-select: text ,使内容可以选择。你可以用这个值来覆盖user-select: none 。
user-select: contain 是一个有趣的问题。应用它意味着,如果一个选择在元素内开始,那么它也必须在元素内结束,包含它。但奇怪的是,当选择开始于元素之前时,这一点并不适用,这可能是目前没有浏览器支持它的原因。(Internet Explorer和早期版本的Microsoft Edge曾以 的名义支持它)。user-select: element
有了user-select: all ,选择元素的部分内容就会自动选择所有的内容。这是全部或没有,这是非常不妥协的,但在用户更可能复制内容到他们的剪贴板的情况下很有用(例如分享和嵌入链接,代码片段等)。用户将不需要双击,而只需要点击一次就可以自动选择内容了。
但要小心,因为这并不总是你认为的那样的功能。如果用户只想选择部分内容(如只选择谷歌字体片段的字体名称部分或代码片段的一个部分)怎么办?在许多情况下,使用JavaScript处理 "复制到剪贴板"还是比较好的。
user-select: all 的一个更好的应用是确保引号被完全和准确地复制。
user-select: auto (user-select 的初始值)的行为取决于元素和它的使用方式。你可以在我们的年鉴中找到更多这方面的信息。
现在让我们转向探索user-select: none的用例 ...
从选择中剥离非文本
当你从一个网页上复制内容时,它可能是来自一篇文章或其他类型的长篇内容,对吗?你可能不希望你的选择包括图片、表情符号(有时可以作为文本复制,例如":thinkingface:"),以及其他你可能期望在<aside> 元素中包裹的东西(例如文章中的行动呼吁、广告,或其他不属于主要内容的东西)。
为了防止某些东西被包含在选择中,确保它被包裹在一个HTML元素中,然后对它应用user-select: none:
<p>lorem <span style="user-select: none">🤔</span> ipsum</p>
<aside style="user-select: none">
<h1>Heading</h1>
<p>Paragraph</p>
<a>Call to action</a>
</aside>
在这样的情况下,我们不是在禁用选择,而是在优化它。还值得一提的是,选择并不一定意味着复制--许多读者(包括我自己)喜欢在阅读时选择内容,这样他们就能记住自己的位置(像书签一样),这是优化而不是完全禁止的另一个原因。
防止意外选择
对看起来像按钮的链接应用user-select: none (例如:<a href="/whatever" class="button">Click Me!</a> )。
不可能选择<button> 或<input type="submit"> 的文本内容,因为,你为什么要这样做?然而,这种行为并不适用于链接,因为传统上它们是一个段落的一部分,应该可以选择。
这很公平。
我们可以争辩说,让链接看起来像按钮是一种反模式,但不管怎样。这并没有破坏互联网,不是吗?无论如何,这艘船已经起航了,所以如果你使用看起来像按钮的链接,那么它们应该模仿按钮的行为,不仅仅是为了一致性,而且是为了防止用户意外地选择内容而不是触发交互。
我当然很容易意外地选择东西,因为我在床上使用笔记本的次数比我愿意承认的要多。另外,有一些医疗条件会影响控制和协调,把有意的点击变成无意的拖动/选择,所以也有可及性问题,可以用user-select 。
当然,需要拖动(故意的)的互动也是存在的(例如在浏览器游戏中),但这些是不常见的。不过,这只是表明user-select ,事实上有相当多的用例。
避免付费内容被盗
付费内容得到了很多人的憎恨,但如果你觉得你需要保护你的内容,那就是你的内容--没有人有权利仅仅因为他们不相信他们应该为它付费而偷窃它。
如果你确实想走这条路,有很多方法可以让用户更难绕过付费墙(或类似地,复制受版权保护的内容,如他人的出版作品)。
用CSS将内容模糊化:
article { filter: blur(<radius>); }
禁用DevTools的键盘快捷键:
document.addEventListener("keydown", function (e) {
if (e.keyCode == 123) e.preventDefault();
else if ((e.ctrlKey || e.metaKey) && e.altKey && e.keyCode == 73) e.preventDefault();
else if ((e.ctrlKey || e.metaKey) && e.altKey && e.keyCode == 74) e.preventDefault();
else if ((e.ctrlKey || e.metaKey) && e.altKey && e.keyCode == 85) e.preventDefault();
});
通过禁用上下文菜单本身来禁止通过上下文菜单访问DevTools:
document.addEventListener("contextmenu", e => e.preventDefault())
当然,为了防止用户在不允许从源头阅读内容时复制内容,应用user-select: none 。
<article style="user-select: none">
还有其他用例吗?
这是我能想到的防止文本选择的三个用例。我还想到了其他几种情况,但它们似乎都很夸张。但你呢?你是否曾在任何情况下禁用过文本选择?我很想知道。