有没有一种方法可以使 HTML 页面上的文本无法被选中?

149

我正在构建一个HTML界面,其中包含一些文本元素,比如标签名称,在选定后看起来很糟糕。不幸的是,用户双击标签名称很容易在许多浏览器中默认将其选中。

我可能可以用JavaScript的技巧来解决这个问题(我也想看到那些答案)--但我真的希望有一些CSS/HTML直接适用于所有浏览器的方法。


2
虽然这里列出的许多示例都可以工作,但请记住,没有什么可以阻止某人查看源代码并复制文本。 - Ren
根据您的需求,https://dev59.com/aG855IYBdhLWcg3w1oE8 也可能是一个适用的解决方案。 - ThiefMaster
16个回答

208
在大多数浏览器中,可以使用CSS实现这一点:
*.unselectable {
   -moz-user-select: -moz-none;
   -khtml-user-select: none;
   -webkit-user-select: none;

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

对于IE<10和Opera浏览器,您需要使用元素的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"));

18
你可以使用选择器 [unselectable=on]{...},这样你就可以避免添加多余的类,并保持原有含义不变。 - venimus
1
根据 http://dev.l-c-n.com/CSS3-selectors/browser-support.php 的说法,这个选择器应该支持IE8及以上版本,可能也支持IE7。 - EricP
2
只是好奇,使用样式表中的*.unselectable是否比.unselectable更有优势? - undefined
1
@venimus 我更倾向于使用类而不是像CSS中的[unselectable=on]这样的xpath选择器。在jquery中,如果您首先缩小到一个立即容器,则它们很好,但在CSS中,选择器从右到左解析,因此仍然是对每个元素和每个元素的unselectable属性进行全面检查,使用性能一般的xpath引擎。同样,我相信querySelector API也是如此,我猜它通常直接连接到CSS / xpath选择器引擎。随着浏览器找到性能调整,这可能会发生变化,但当支持IE <= 8时,我肯定会记住这一点,也许是<=9。 - Erik Reppen
@venimus:如果你想支持IE <= 9并且不想在每个元素上添加“unselectable =” on“”,那么你无法避免JS。你可以通过选择器避免添加“class =” unselectable“的所有内容。 - Tim Down
显示剩余6条评论

41
<script type="text/javascript">

/***********************************************
* Disable Text Selection script- © Dynamic Drive DHTML code library (www.dynamicdrive.com)
* This notice MUST stay intact for legal use
* Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code

***********************************************/


function disableSelection(target){

    if (typeof target.onselectstart!="undefined") //IE route
        target.onselectstart=function(){return false}

    else if (typeof target.style.MozUserSelect!="undefined") //Firefox route
        target.style.MozUserSelect="none"

    else //All other route (ie: Opera)
        target.onmousedown=function(){return false}

    target.style.cursor = "default"
}



//Sample usages
//disableSelection(document.body) //Disable text selection on entire body
//disableSelection(document.getElementById("mydiv")) //Disable text selection on element with id="mydiv"


</script>

编辑

代码显然来自http://www.dynamicdrive.com


有没有关于Opera的更新,或者使元素不可选择仍然不支持的消息? - jayarjo
在最后一个情况下为什么要将鼠标样式更改为“默认”?否则+1。 - HRJ
4
实际上,在所有情况下,您都在进行更改(缩进是误导性的)。 - HRJ

36

所有正确的CSS变体如下:

-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;

1
根据这个答案,这两个webkit设置的顺序可能很关键,其中-webkit-user-select:应该放在-webkit-touch-callout:之前。我没有验证过。 - Basil Bourque

13

试一下这个:

<div onselectstart="return false">some stuff</div>

简单而有效...适用于所有主流浏览器的当前版本。


1
这在我的火狐浏览器上不起作用。 - Tyler
这是仅适用于IE的属性,使其变得多余。 - vsync
2
我们的应用程序在使用过程中完美运行(我们只针对IE用户)。 - Lee
这是我在ag-Grid中进行shift-click选择时,在IE11中实现所需的文本选择效果的唯一方法。 - Mark Hughes

11
对于Firefox,您可以将CSS声明“-moz-user-select”应用于“none”。 请查看他们的文档,user-select
正如他们所说,这是未来“user-select”的“预览”,因此Opera或基于WebKit的浏览器可能会支持它。我还记得在Internet Explorer中找到了一些东西,但我不记得是什么。
无论如何,除非在某些特定情况下,文本选择会导致某些动态功能失败,否则您不应该覆盖用户从网页中期望的内容,即能够选择任何想要的文本。

5
同样在Safari/Chrome等浏览器中使用-khtml-user-select:none; - Brandon DuRette
1
这个是否可能出现在CSS标准中呢? - Andrew Harry

9

我使用此处所描述的CSS http://www.quirksmode.org/css/selection.html 取得了一定的成功:

::selection {
    background-color: transparent;
}

它解决了我在AIR应用程序(WebKit引擎)中使用ThemeRoller ul元素时遇到的大部分问题。仍然存在一个小的空白区域(约15 x 15),会被选中,但之前整个页面的一半都被选中。


6
在文本区域上方绝对定位div,并将这些div的z-index设置得更高,给这些div一个透明的GIF背景图。请注意,在进一步思考后,您需要使这些“覆盖”与链接相关,因此单击它们会将您带到选项卡所在的位置,这意味着您可以/应该使用设置为display:box、宽度和高度以及透明背景图像的锚元素来完成此操作。

这就是Flickr的功能。 - Andrew Harry
20
这种黑客手段很糟糕。就我个人而言,我会避免使用它。 - Doug
这种方法的微小问题在于链接,正如你所提到的,以及您想要与主窗口进行的任何其他交互... - Alexis Wilke

4

对于Safari浏览器,使用-khtml-user-select: none,就像Mozilla的-moz-user-select一样(或者在JavaScript中使用target.style.KhtmlUserSelect="none";)。


4

举个例子说明为什么可能希望禁止选择,请参见SIMILE Timeline。该网站使用拖放功能浏览时间轴,但意外的垂直鼠标移动会导致标签被意外地突出显示,这看起来很奇怪。


3
这里是一个Sass mixin (scss),供那些有兴趣的人使用。Compass/CSS 3似乎没有user-select mixin。
// @usage use within a rule
// ex. img {@include user-select(none);}
// @param assumed valid user-select value
@mixin user-select($value)
{
    & {
        -webkit-touch-callout: $value;
        -webkit-user-select: $value;
        -khtml-user-select: $value;
        -moz-user-select: $value;
        -ms-user-select: $value;
        user-select: $value;
    }
}

尽管Compass会以更加健壮的方式实现,即仅添加您选择的供应商支持。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接