How to make HTML Text unselectable [duplicate]
Asked Answered
W

4

245

I would like to add text to my webpage as a label and make it unselectable.

In other words, When the mouse cursor is over the text I would like it to not turn into a text selecting cursor at all.

A good example of what I'm trying to achieve is the buttons on this website (Questions,Tags,Users,...)

Wittenberg answered 22/2, 2010 at 12:12 Comment(0)
C
381

You can't do this with plain vanilla HTML, so JSF can't do much for you here as well.

If you're targeting decent browsers only, then just make use of CSS3:

.unselectable {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
<label class="unselectable">Unselectable label</label>

If you'd like to cover older browsers as well, then consider this JavaScript fallback:

<!doctype html>
<html lang="en">
    <head>
        <title>SO question 2310734</title>
        <script>
            window.onload = function() {
                var labels = document.getElementsByTagName('label');
                for (var i = 0; i < labels.length; i++) {
                    disableSelection(labels[i]);
                }
            };
            function disableSelection(element) {
                if (typeof element.onselectstart != 'undefined') {
                    element.onselectstart = function() { return false; };
                } else if (typeof element.style.MozUserSelect != 'undefined') {
                    element.style.MozUserSelect = 'none';
                } else {
                    element.onmousedown = function() { return false; };
                }
            }
        </script>
    </head>
    <body>
        <label>Try to select this</label>
    </body>
</html>

If you're already using jQuery, then here's another example which adds a new function disableSelection() to jQuery so that you can use it anywhere in your jQuery code:

<!doctype html>
<html lang="en">
    <head>
        <title>SO question 2310734 with jQuery</title>
        <script src="http://code.jquery.com/jquery-latest.min.js"></script>
        <script>
            $.fn.extend({ 
                disableSelection: function() { 
                    this.each(function() { 
                        if (typeof this.onselectstart != 'undefined') {
                            this.onselectstart = function() { return false; };
                        } else if (typeof this.style.MozUserSelect != 'undefined') {
                            this.style.MozUserSelect = 'none';
                        } else {
                            this.onmousedown = function() { return false; };
                        }
                    }); 
                } 
            });

            $(document).ready(function() {
                $('label').disableSelection();            
            });
        </script>
    </head>
    <body>
        <label>Try to select this</label>
    </body>
</html>
Cochineal answered 22/2, 2010 at 12:31 Comment(9)
This answer has a problem, and it does not work in all cases any more. Other browsers use their own vendor prefixes, and you are using MozUserSelect only. New browsers will use no prefix. Look at the list of all possible javascript prefixes: ['Moz', 'Webkit', 'ms', 'O', 'Khtml', ''] /*with empty string for no prefix*/. You should correctly deal with camelCase. And it's a serious bug that you are overwriting onselectstart and onmousedown event handlers with your function, so previously attached handlers do not work any more. I can Update your code if you likeBalsa
@Cochineal as far as I see here developer.mozilla.org/en-US/docs/Web/CSS/user-select, you still can't do this cross browser with CSS only (old IE, Opera and Firefox). So a good hybrid solution is neededBalsa
And @Blowsie has reported problems in comments.Balsa
caniuse.com/user-select-noneBalsa
If you do end up adding the disableSelection to jQuery - I did, and it works great, but give it another name. In case you end up using jQuery UI there's a name conflict when using plugins like resizable. Just a heads up.Dorsal
try like this - *.unselectable { ... }Gabrila
That's why I love being a developer, now I found how to copy some piece of text they don't want me to copy. Just search for the problem they probably had :).Cenac
I want to know how one would undo the jquery function. Like $(".element").mousedown(function() { $('body').disableSelection(); )}; $(window).mouseup(function() { $('body').undoThedisableSelectionFunction(); });Delude
You or someone here might do an easy job of answering this question #70931070Delude
P
185

No one here posted an answer with all of the correct CSS variations, so here it is:

.not-selectable {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
<p class="not-selectable">Not-selectable text</p>
Parabolize answered 17/6, 2011 at 7:9 Comment(8)
These do work well in modern browsers, but be aware that older ones like IE7 will not support this.Buttercup
In Chrome 18, this is only a visual effect, the text is still selectable.Disillusion
Can still select text in Opera 11Shorts
Can still select text in Opera.Parka
For Opera, does the '-o-' prefix work?Gaspard
@Gaspard Might be worth sticking it in just in case.Beriberi
CSS does not work in Chrome Version 56.0.2924.87 (64-bit). Still copies to clipboard...Britton
@RonRoyston the questions is about selecting not copying. But maybe u want this.Convalescent
T
63

The full modern solution to your problem is purely CSS-based, but note that older browsers won't support it, in which cases you'd need to fallback to solutions such as the others have provided.

So in pure CSS:

-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;

However the mouse cursor will still change to a caret when over the element's text, so you add to that:

cursor: default;

Modern CSS is pretty elegant.

Tintype answered 23/11, 2011 at 16:4 Comment(5)
you call that modern? having to specify the same thing 6 times?Mena
yeah I hate the browser prefixes too but oh well they have a history of not agreeing so we got used to having these around.Tintype
@Mena I use less, so I only have to write this snippet once! :)Jarrell
You can also use SASS and specify a mixin for that.Tow
Specifying the cursor seems to be no longer needed. It will change to default automatically with the correct variation of user-select: none. Tested in Firefox 61.0.1 and Vivaldi 1.15.1147.47.Limp
L
12

I altered the jQuery plugin posted above so it would work on live elements.

(function ($) {
$.fn.disableSelection = function () {
    return this.each(function () {
        if (typeof this.onselectstart != 'undefined') {
            this.onselectstart = function() { return false; };
        } else if (typeof this.style.MozUserSelect != 'undefined') {
            this.style.MozUserSelect = 'none';
        } else {
            this.onmousedown = function() { return false; };
        }
    });
};
})(jQuery);

Then you could so something like:

$(document).ready(function() {
    $('label').disableSelection();

    // Or to make everything unselectable
    $('*').disableSelection();
});
Laundryman answered 21/2, 2011 at 20:40 Comment(1)
This was a great answer, but unfortunately it got outdated. See my comment to @Cochineal answerBalsa

© 2022 - 2024 — McMap. All rights reserved.