如何禁用文本选择突出显示

对于充当按钮的锚(例如,“堆栈溢出” 页面顶部的 “ 问题” ,“ 标签” ,“ 用户 ” 等)或选项卡,是否存在 CSS 标准方法来禁用突出显示效果(如果用户不小心选择了文本)?

我意识到可以使用 JavaScript 来完成此操作,并且经过一番搜寻后发现了仅 Mozilla 的-moz-user-select选项。

是否有使用 CSS 来实现此目标的符合标准的方法,如果没有,“最佳实践” 方法是什么?

答案

2017 年 1 月更新:

根据我可以使用 ,除 Internet Explorer 9 和更早版本外,所有浏览器当前都支持user-select (但遗憾的是, 需要供应商前缀)。


所有正确的 CSS 变体是:

.noselect {
  -webkit-touch-callout: none; /* iOS Safari */
    -webkit-user-select: none; /* Safari */
     -khtml-user-select: none; /* Konqueror HTML */
       -moz-user-select: none; /* Old versions of Firefox */
        -ms-user-select: none; /* Internet Explorer/Edge */
            user-select: none; /* Non-prefixed version, currently
                                  supported by Chrome, Opera and Firefox */
}
<p>
  Selectable text.
</p>
<p class="noselect">
  Unselectable text.
</p>


请注意,这是非标准功能 (即不是任何规范的一部分)。不能保证它在任何地方都能工作,并且浏览器的实现可能会有所不同,将来浏览器可能会放弃对此的支持。


可以在Mozilla 开发人员网络文档中找到更多信息。

在大多数浏览器中,这可以通过使用 CSS user-select属性的专有变体来实现,该属性最初是在 CSS 3 中提出,然后在 CSS 3 中放弃,而现在在CSS UI Level 4 中提出的:

*.unselectable {
   -moz-user-select: none;
   -khtml-user-select: none;
   -webkit-user-select: none;

   /*
     Introduced in Internet Explorer 10.
     See http://ie.microsoft.com/testdrive/HTML5/msUserSelect/
   */
   -ms-user-select: none;
   user-select: none;
}

对于 Internet Explorer <10 和Opera <15,您将需要使用希望不可选择的元素的unselectable属性。您可以使用 HTML 中的属性进行设置:

<div id="foo" unselectable="on" class="unselectable">...</div>

遗憾的是,该属性没有被继承,这意味着您必须在<div>内每个元素的开始标记中放置一个属性。如果这是一个问题,则可以改用 JavaScript 为元素的后代递归执行此操作:

function makeUnselectable(node) {
    if (node.nodeType == 1) {
        node.setAttribute("unselectable", "on");
    }
    var child = node.firstChild;
    while (child) {
        makeUnselectable(child);
        child = child.nextSibling;
    }
}

makeUnselectable(document.getElementById("foo"));

更新 2014 年 4 月 30 日 :这树遍历需要重新运行每当一个新的元素被添加到树上,但由 @Han,有可能通过增加以避免这样的评论似乎mousedown事件处理程序,设置unselectable目标事件的有关详细信息,请参见http://jsbin.com/yagekiji/1


这仍然不能涵盖所有可能性。尽管无法在不可选择的元素中启动选择,但是在某些浏览器(例如 Internet Explorer 和 Firefox)中,仍然无法防止在不可选择的元素之前和之后开始的选择而不会使整个文档不可选择。

Internet Explorer 的 JavaScript 解决方案是:

onselectstart="return false;"

在 CSS 3 的user-select属性可用之前,基于Gecko的浏览器将支持您已经找到的-moz-user-select属性。 基于 WebKit和基于 Blink 的浏览器支持-webkit-user-select属性。

当然,在不使用 Gecko 渲染引擎的浏览器中不支持此功能。

没有兼容 “标准” 的快捷方法。使用 JavaScript 是一种选择。

真正的问题是,为什么您希望用户无法突出显示并可能复制并粘贴某些元素?我没有一次不想让用户强调我网站的特定部分。我的几个朋友在花费大量时间阅读和编写代码之后,将使用突出显示功能来记住他们在页面上的位置,或者提供标记以使他们的眼睛知道接下来要去哪里。

我能看到的唯一有用的地方是,如果您有用于表单的按钮,并且用户复制并粘贴了网站,则该按钮不应被复制并粘贴。

如果要禁用除<p>元素以外的所有内容的文本选择,则可以在 CSS 中执行此操作(请注意-moz-none ,它允许在子元素中进行覆盖,而在其他浏览器中则不允许使用none元素):

* {
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: -moz-none;
    -o-user-select: none;
    user-select: none;
}

p {
    -webkit-user-select: text;
    -khtml-user-select: text;
    -moz-user-select: text;
    -o-user-select: text;
    user-select: text;
}

在先前答案中的解决方案中,选择已停止,但用户仍然认为您可以选择文本,因为光标仍在变化。要使其保持静态,您必须设置 CSS 光标:

.noselect {
    cursor: default;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
<p>
  Selectable text.
</p>
<p class="noselect">
  Unselectable text.
</p>

这将使您的文本完全平坦,就像在桌面应用程序中一样。

您可以在 Firefox 和 Safari(Chrome 也可以吗?)中这样做

::selection { background: transparent; }
::-moz-selection { background: transparent; }

WebKit 的解决方法:

/* Disable tap highlighting */
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);

我在 CardFlip 示例中找到了它。

我喜欢混合 CSS + jQuery 解决方案。

要使<div class="draggable"></div>内的所有元素<div class="draggable"></div>可选择,请使用以下 CSS:

.draggable {
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -o-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.draggable input {
    -webkit-user-select: text;
    -khtml-user-select: text;
    -moz-user-select: text;
    -o-user-select: text;
    user-select: text;
 }

然后,如果您使用的是 jQuery,请将其添加到$(document).ready()块中:

if (($.browser.msie && $.browser.version < 10) || $.browser.opera) $('.draggable').find(':not(input)').attr('unselectable', 'on');

我认为您仍然希望任何输入元素都是可交互的,因此:not()伪选择器。如果您不在乎,则可以使用'*'代替。

注意:Internet Explorer 9 可能不需要这个额外的 jQuery,因此您可能需要在其中添加版本检查。

.hidden:after {
    content: attr(data-txt);
}
<p class="hidden" data-txt="Some text you don't want to be selected"></p>

不过,这不是最好的方法。