237

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,...)

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Ben
  • 10,020
  • 21
  • 94
  • 157

4 Answers4

374

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>
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    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 like – Dan Jul 18 '13 at 09:45
  • @BalusC as far as I see here https://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 needed – Dan Jul 18 '13 at 12:54
  • And @Blowsie has reported problems in comments. – Dan Jul 18 '13 at 12:55
  • 2
    http://caniuse.com/user-select-none – Dan Jul 18 '13 at 13:01
  • 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. – webdreamer Jan 13 '15 at 15:14
  • try like this - `*.unselectable { ... }` – Rohit Suthar Mar 01 '17 at 12:13
  • 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 :). – CularBytes Aug 03 '20 at 19:01
  • I want to know how one would undo the jquery function. Like `$(".element").mousedown(function() { $('body').disableSelection(); )}; $(window).mouseup(function() { $('body').undoThedisableSelectionFunction(); });` – Jevon Jan 31 '22 at 17:10
  • You or someone here might do an easy job of answering this question https://stackoverflow.com/questions/70930570/how-to-make-whole-document-selectable-after-making-it-unselectable – Jevon Jan 31 '22 at 17:52
183

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>
Blowsie
  • 40,239
  • 15
  • 88
  • 108
62

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.

ecoe
  • 4,994
  • 7
  • 54
  • 72
Vic Goldfeld
  • 1,179
  • 12
  • 15
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();
});
Steve
  • 227
  • 3
  • 4
  • 1
    This was a great answer, but unfortunately it got outdated. See my comment to @BalusC answer – Dan Jul 18 '13 at 09:51