Is there a way to make text unselectable on an HTML page?
Solution 1
In most browsers, this can be achieved using 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;
}
For IE < 10 and Opera, you will need to use the unselectable
attribute of the element you wish to be unselectable. You can set this using an attribute in HTML:
<div id="foo" unselectable="on" class="unselectable">...</div>
Sadly this property isn't inherited, meaning you have to put an attribute in the start tag of every element inside the <div>
. If this is a problem, you could instead use JavaScript to do this recursively for an element's descendants:
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"));
Solution 2
<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>
EDIT
Code apparently comes from http://www.dynamicdrive.com
Solution 3
All of the correct CSS variations are:
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
Solution 4
Try this:
<div onselectstart="return false">some stuff</div>
Simple, but effective... works in current versions of all major browsers.
Solution 5
For Firefox you can apply the CSS declaration "-moz-user-select" to "none". Check out their documentation, user-select.
It's a "preview" of the future "user-select" as they say, so maybe Opera or WebKit-based browsers will support that. I also recall finding something for Internet Explorer, but I don't remember what :).
Anyway, unless it's a specific situation where text-selecting makes some dynamic functionality fail, you shouldn't really override what users are expecting from a webpage, and that is being able to select any text they want.
Tyler
I run an iPhone app consultancy called Bynomial. Please let me know if you're interested in app development! I'm always looking for good coders and good clients. My background: I love math -- I got a PhD in it from the Courant Institute at NYU in 2006. After that I was a coder at Google for a few years, and in 2009 started Bynomial.
Updated on April 17, 2020Comments
-
Tyler about 4 years
I'm building an HTML UI with some text elements, such as tab names, which look bad when selected. Unfortunately, it's very easy for a user to double-click a tab name, which selects it by default in many browsers.
I might be able to solve this with a JavaScript trick (I'd like to see those answers, too) -- but I'm really hoping there's something in CSS/HTML directly that works across all browsers.
-
Brandon DuRette over 15 yearsLikewise in Safari/Chrome/etc. -khtml-user-select:none;
-
Andrew Harry over 15 yearsThis is what flickr does
-
Andrew Harry over 15 yearsIs this likely to appear in the CSS standards though?
-
Tyler almost 15 yearsThis doesn't work for me in firefox.
-
vsync over 14 yearsThis is IE only attribute. which makes it redundant.
-
jayarjo about 14 yearsIs there any update for the Opera or making elements unselectable still not supported?
-
HRJ almost 14 yearsWhy are you changing the cusor style to 'default' in the last case? Otherwise +1
-
HRJ almost 14 yearsInfact, you are changing it in all cases (indent is misleading)
-
Doug almost 14 yearsThis kind of hack is terrible. I'd avoid it personally.
-
Lee over 13 yearsWorked perfectly for our app (we only target IE users).
-
Hubro over 13 yearsI guess body might not be accessible in DOM before it has content, thus you can't set it's style before you write something in the document.
-
venimus about 13 yearsyou can use this selector [unselectable=on]{...} then you avoid putting extra class
-
EricP over 12 yearsAccording to dev.l-c-n.com/CSS3-selectors/browser-support.php , this selector should be supported in IE8 and above, and possibly IE7.
-
Tim Down over 12 years@JoeCoder: Yes, I believe attribute selectors do work in IE 7, although not IE 6.
-
undefined over 11 yearsJust curious, is there an advantage to using *.unselectable over .unselectable in the stylesheet?
-
Tim Down over 11 years@BrianMortenson: None at all: they are equivalent. I have a very old habit of including the
*
in that kind of selector to remind myself explicitly that I'm matching all tag names. However, I no longer find it helpful and it's now just pure habit, so I've pretty much stopped doing it now. -
ericsoco almost 11 yearsfunny that @TimDown harvested another 113 rep by copying his answer from this question's duplicate. oh wait! <click> 114 ;)
-
Tim Down almost 11 years@ericsoco: Yeah. It's an interesting issue: if others have posted answers that people are upvoting and I think I have a better answer, should I post it? The system still allows people to find, view and vote on answers to closed questions, after all. I can't deny that desire for rep has occasionally motivated me to add an answer to a duplicate question on a pet subject rather than vote to close it.
-
ericsoco almost 11 yearsof course you should and of course you should post your answers everywhere they can be found. the point of answering, ultimately, is not about rep -- it's about providing answers in places they can be found. i'm all for it. </OT>
-
Erik Reppen over 10 years@venimus I would favor classes over xpath selectors like [unselectable=on] in CSS. In jquery they're good if you narrow down to an immediate container first but in CSS, selectors are parsed right to left so it's still a blanket check of every element and every element's unselectable attribute using the performance-meh xpath engine. Likewise, I believe, with the querySelector API which I'm guessing typically hooks into the CSS/xpath selector engines directly. This may change over time as browsers find perf tweaks but I would definitely keep this in mind when supporting IE<=8, maybe <=9.
-
venimus over 10 yearsProbably you are right, but I think early optimizations are evil. Also you won't need the JS if you use [unselectable=on] * {...}
-
Tim Down over 10 years@venimus: You can't avoid the JS if you want IE <= 9 support and don't want to put
unselectable="on"
on every element. All you can avoid with your selector is addingclass="unselectable"
. -
Basil Bourque over 9 yearsAccording to this Answer, the order of those two webkit settings may be critical, where the
-webkit-user-select:
should come before the-webkit-touch-callout:
. I have not verified this. -
Alexis Wilke over 8 yearsThe tiny little problem with this method are the links, as you mentioned, and any other interactions you'd want to have with the main window...
-
Mark Hughes over 7 yearsThis was the only way I could get the effect needed for text selection happening in IE11 when doing a shift-click select in an ag-Grid.