何时可以禁用文本选择?

Avatar of Daniel Schwarz
Daniel Schwarz

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 $200 免费积分!

使用 CSS,可以通过 user-select: none 来阻止用户选择元素内的文本。 现在,可以理解为什么这样做可能被认为是“有争议的”。 我的意思是,我们应该禁用标准的用户行为吗? 一般来说,不,我们不应该这样做。 但是禁用文本选择是否有一些合法的(尽管很少见)用例? 我认为是。

在本文中,我们将探讨这些用例,并了解如何使用 user-select: none 来改善(而不是阻碍)用户体验。 值得注意的是,user-select 属性除了 none 之外还有其他值,这些值可用于更改文本选择的行为,而不是完全禁用它,以及另一个强制执行文本选择的值,因此我们也将看看这些值。

可能的 user-select

让我们从遍历不同的 user-select 值及其功能开始。

user-select: none; 应用于元素意味着其文本内容和嵌套文本内容将无法在功能上或视觉上被选择(即 ::selection 不起作用)。 如果您要进行包含一些不可选择内容的选择,则不可选择内容将从选择中省略,因此实现相当完善。 而且支持度很高。

此浏览器支持数据来自 Caniuse,其中提供了更多详细信息。 数字表示浏览器在该版本及更高版本上支持该功能。

桌面

ChromeFirefoxIEEdgeSafari
4*2*10*12*3.1*

移动设备/平板电脑

Android ChromeAndroid FirefoxAndroidiOS Safari
1271272.1*3.2*

相反,user-select: text 使内容可选择。 您可以使用此值覆盖 user-select: none

user-select: contain 很有趣。 应用它意味着如果选择从元素内部开始,那么它也必须在元素内部结束,包含它。 但是,这在选择从元素之前开始时却奇怪地不适用,这可能就是目前没有浏览器支持它的原因。(Internet Explorer 和早期版本的 Microsoft Edge 以前在 user-select: element 的掩护下支持它。)

使用 user-select: all,选择元素内容的一部分会导致所有内容自动被选择。 这是全有或全无,非常不妥协,但在用户更有可能将内容复制到剪贴板的情况下很有用(例如,共享和嵌入链接、代码片段等)。 用户只需单击一次即可自动选择内容,而无需双击。

但要小心,因为这并不总是您认为的功能。 如果用户只想选择内容的一部分(例如,Google Fonts 代码片段中只有字体名称部分,或者代码片段中的一小部分)呢? 在许多情况下,使用 JavaScript 处理“复制到剪贴板” 仍然更好。

user-select: all 的一个更好的应用是确保完全准确地复制引号。

user-select: autouser-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">单击我!</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">

还有其他用例吗?

这些是我能想到的三个防止文本选择的用例。 我脑海中闪过其他一些,但它们似乎都有些牵强。 但是您呢? 您是否曾经在任何地方禁用文本选择? 我想知道!