[css] How to disable text selection highlighting

For anchors that act like buttons (for example Questions, Tags, Users, etc. which are located on the top of the Stack Overflow page) or tabs, is there a CSS standard way to disable the highlighting effect if the user accidentally selects the text?

I realize that this could be done with JavaScript and a little googling yielded the Mozilla-only -moz-user-select option.

Is there a standard-compliant way to accomplish this with CSS, and if not, what is the "best practice" approach?

This question is related to css cross-browser highlight textselection

The answer is


It is easily done with:

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

Alternatively:

Let's say you have a <h1 id="example">Hello, World!</h1>. You will have to remove the innerHTML of that h1, in this case Hello, World. Then you will have to go to CSS and do this:

#example::before // You can of course use **::after** as well.
{
    content: 'Hello, World!'; // Both single-quotes and double-quotes can be used here.

    display: block; // To make sure it works fine in every browser.
}

Now it simply thinks it is a block-element, and not text.


I have learned from the CSS-Tricks website.

user-select: none;

And this also:

::selection {
    background-color: transparent;
}

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

::webkit-selection {
    background-color: transparent;
}

A Quick Hack Update

If you use the value none for all the CSS user-select properties (including browser prefixes of it), there is a problem which can be still occurred by this.

.div {
    -webkit-user-select: none; /* Chrome all / Safari all */
    -moz-user-select: none;    /* Firefox all             */
    -ms-user-select: none;     /* Internet Explorer  10+  */
     user-select: none;        /* Likely future           */
}

As CSS-Tricks says, the problem is:

WebKit still allows the text to be copied, if you select elements around it.

You can also use the below one to enforce that an entire element gets selected which means if you click on an element, all the text wrapped in that element will get selected. For this all you have to do is changing the value none to all.

.force-select {
    -webkit-user-select: all;  /* Chrome 49+     */
    -moz-user-select: all;     /* Firefox 43+    */
    -ms-user-select: all;      /* No support yet */
    user-select: all;          /* Likely future  */
}

This works in some browsers:

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

Simply add your desired elements/ids in front of the selectors separated by commas without spaces, like so:

h1::selection,h2::selection,h3::selection,p::selection{ background-color: transparent;}
h1::moz-selection,h2::moz-selection,h3::moz-selection,p::moz-selection{ background-color: transparent;}
h1::webkit-selection,h2::webkit-selection,h3::webkit-selection,p::webkit-selection{ background-color: transparent;}

The other answers are better; this should probably be seen as a last resort/catchall.


You can use a *-user-select property as below for that...

p {
    -webkit-user-select: none;  /* Chrome all and Safari all */
    -moz-user-select: none;     /* Firefox all */
    -ms-user-select: none;      /* Internet Explorer 10 and later */
    user-select: none;          /* Likely future */
}

Link for the Detailed Description


Even better, you can disable text selection.

If you like Sass (SCSS), and you don't want to use Compass you can do this:

styles.scss

@mixin user-select($select) {
    -webkit-touch-callout:#{$select};
    @each $pre in -webkit-, -moz-, -ms-, -o-, -khtml- {
        #{$pre + user-select}: #{$select};
    }
    #{user-select}: #{$select};
}

.no-select {
    @include user-select(none);
}

Use:

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

For Internet Explorer in addition, you need to add pseudo class focus (.ClassName:focus) and outline-style: none.

.ClassName,
.ClassName:focus {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    outline-style: none; /* Internet Explorer  */
}

::selection {background: transparent; color: transparent;}

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

Aside from the Mozilla-only property, no, there is no way to disable text selection with just standard CSS (as of now).

If you notice, Stack Overflow doesn't disable text selection for their navigation buttons, and I would recommend against doing so in most cases, since it modifies normal selection behavior and makes it conflict with a user's expectations.


If you want to disable selection and highlighting for the whole page you can easily do this with CSS:

* {
    -webkit-touch-callout: none; /* iOS Safari */
      -webkit-user-select: none; /* Safari */
       -khtml-user-select: none; /* Konqueror HTML */
         -moz-user-select: none; /* Firefox */
          -ms-user-select: none; /* Internet Explorer/Edge */
              user-select: none; /* Non-prefixed version, currently
                                    supported by Chrome and Opera */
}

Until CSS 3's user-select property becomes available, Gecko-based browsers support the -moz-user-select property you already found. WebKit and Blink-based browsers support the -webkit-user-select property.

This of course is not supported in browsers that do not use the Gecko rendering engine.

There is no "standards" compliant quick-and-easy way to do it; using JavaScript is an option.

The real question is, why do you want users to not be able to highlight and presumably copy and paste certain elements? I have not come across a single time that I wanted to not let users highlight a certain portion of my website. Several of my friends, after spending many hours reading and writing code will use the highlight feature as a way to remember where on the page they were, or providing a marker so that their eyes know where to look next.

The only place I could see this being useful is if you have buttons for forms that should not be copy and pasted if a user copy and pasted the website.


<script type="text/javascript">

if(typeof document.onselectstart!="undefined"){
document.onselectstart=new Function ("return false");
}
else{
document.onmousedown= new Function ("return false");
document.onmouseup= new Function ("return true");
}
</script>

A JavaScript solution for Internet Explorer is:

onselectstart="return false;"

NOTE:

The correct answer is correct in that it prevents you from being able to select the text. However, it does not prevent you from being able to copy the text, as I'll show with the next couple of screenshots (as of 7th Nov 2014).

Before we have selected anything

After we have selected

The numbers have been copied

As you can see, we were unable to select the numbers, but we were able to copy them.

Tested on: Ubuntu, Google Chrome 38.0.2125.111.


Workaround for WebKit:

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

I found it in a CardFlip example.


This will be useful if color selection is also not needed:

::-moz-selection { background:none; color:none; }
::selection { background:none; color:none; }

...all other browser fixes. It will work in Internet Explorer 9 or later.


Did you tried this?

.disableSelect{
    user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    -webkit-touch-callout: none;
    -o-user-select: none;
    -moz-user-select: none;

    pointer-events:none;
}

To get the result I needed, I found I had to use both ::selection and user-select

input.no-select:focus {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

input.no-select::selection {
    background: transparent;
}

input.no-select::-moz-selection {
    background: transparent;
}

With CSS-

_x000D_
_x000D_
div {_x000D_
  -moz-user-select: none;_x000D_
  -webkit-user-select: none;_x000D_
  -ms-user-select: none;_x000D_
  user-select: none;_x000D_
  -o-user-select: none;_x000D_
_x000D_
  "unselectable='on' onselectstart="return false;"_x000D_
  onmousedown="return false;_x000D_
}
_x000D_
<div>_x000D_
  Blabla_x000D_
  <br/> More Blabla_x000D_
  <br/> More Blabla..._x000D_
</div>
_x000D_
_x000D_
_x000D_


You may also want to prevent the context menu appearing when touching elements like buttons that have their selection prevented. To do that, add this code to the entire page, or just those button elements:

$("body").on("contextmenu",function(e){
    return false;
});

In the solutions in previous answers selection is stopped, but the user still thinks you can select text because the cursor still changes. To keep it static, you'll have to set your CSS cursor:

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

This will make your text totally flat, like it would be in a desktop application.


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

It's not the best way, though.


You can do so in Firefox and Safari (Chrome also?)

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

Add this to the first div in which you want to disable the selection for text:

onmousedown='return false;' 
onselectstart='return false;'

A JavaScript-based solution for Internet Explorer is:

onselectstart="return false;"


I like the hybrid CSS + jQuery solution.

To make all elements inside <div class="draggable"></div> unselectable, use this CSS:

.draggable {
    -webkit-user-select: none;
     -khtml-user-select: none;
       -moz-user-select: none;
        -ms-user-select: none;
         -o-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;
 }

And then, if you're using jQuery, add this inside a $(document).ready() block:

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

I figure you still want any input elements to be interactable, hence the :not() pseudo-selector. You could use '*' instead if you don't care.

Caveat: Internet Explorer 9 may not need this extra jQuery piece, so you may want to add a version check in there.


Check my solution without JavaScript:

jsFiddle

_x000D_
_x000D_
li:hover {_x000D_
    background-color: silver;_x000D_
}_x000D_
#id1:before {_x000D_
    content: "File";_x000D_
}_x000D_
#id2:before {_x000D_
    content: "Edit";_x000D_
}_x000D_
#id3:before {_x000D_
    content: "View";_x000D_
}
_x000D_
<ul>_x000D_
    <li><a id="id1" href="www.w1.com"></a>_x000D_
    <li><a id="id2" href="www.w2.com"></a>_x000D_
    <li><a id="id3" href="www.w3.com"></a>_x000D_
</ul>
_x000D_
_x000D_
_x000D_

Popup menu with my technique applied: http://jsfiddle.net/y4Lac/2/


Add a class to your CSS that defines you cannot select or highlight an element. I have an example:

<style> 
    .no_highlighting{
        user-select: none;
    }

    .anchor_without_decoration:hover{
        text-decoration-style: none;
    }
</style>

<a href="#" class="anchor_without_decoration no_highlighting">Anchor text</a>

Try to use this one:

::selection {
    background: transparent;
}

And if you wish to specify not select inside a specific element, just put the element class or id before the selection rule, such as:

.ClassNAME::selection {
    background: transparent;
}
#IdNAME::selection {
    background: transparent;
}

I combined the various browser CSS select attributes with the unselectable tag required for Internet Explorer < 9.

<style>
[unselectable="on"] {
    -webkit-user-select: none; /* Safari */
    -moz-user-select: none; /* Firefox */
    -ms-user-select: none; /* Internet Explorer 10+/Edge */
    user-select: none; /* Standard */
}
</style>
<div unselectable="on">Unselectable Text</div>

If you want to disable text selection on everything except on <p> elements, you can do this in CSS (watch out for the -moz-none which allows override in sub-elements, which is allowed in other browsers with 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;
}

This is not CSS, but it is worth a mention:

jQuery UI Disable Selection:

$("your.selector").disableSelection();

Though this pseudo-element was in drafts of CSS Selectors Level 3, it was removed during the Candidate Recommendation phase, as it appeared that its behavior was under-specified, especially with nested elements, and interoperability wasn't achieved.

It's being discussed in How ::selection works on nested elements.

Despite it is being implemented in browsers, you can make an illusion of text not being selected by using the same color and background color on selection as of the tab design (in your case).

Normal CSS Design

p { color: white;  background: black; }

On selection

p::-moz-selection { color: white;  background: black; }
p::selection      { color: white;  background: black; }

Disallowing users to select the text will raise usability issues.


This highlighting effect is due to the action called hover (onMouseHover).

When you will hover on any tab its color will be changed.

Just say for example,

HTML code

<div class="menu">
    <ul class="effect">
        <li>Questions</li>
        <li>JOBS</li>
        <li>Users</li>
    </ul>
</div>

CSS code

.effect:hover {
    color: none;
}

You can use any color if you want to get it highlighted. Else you can use none.


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

*.unselectable {
   -moz-user-select: -moz-none;
   -khtml-user-select: none;
   -webkit-user-select: none;
   user-select: none;
}
<div id="foo" unselectable="on" class="unselectable">...</div>
function makeUnselectable(node) {
    if (node.nodeType == 1) {
        node.unselectable = true;
    }
    var child = node.firstChild;
    while (child) {
        makeUnselectable(child);
        child = child.nextSibling;
    }
}

makeUnselectable(document.getElementById("foo"));
-webkit-user-select: none;
-moz-user-select: none;
onselectstart="return false;"
::selection { 
    background: transparent; 
}

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

* {
    -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;
}
<div class="draggable"></div>
.draggable {
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -o-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;
 }
if ($.browser.msie)
    $('.draggable').find(':not(input)').attr('unselectable', 'on');

Maybe you can use this solution through :before:

_x000D_
_x000D_
nav li {_x000D_
    display: inline-block;_x000D_
    position: relative;_x000D_
}_x000D_
_x000D_
nav li a {_x000D_
    display: inline-block;_x000D_
    padding: 10px 20px;_x000D_
}_x000D_
_x000D_
nav li a:hover {_x000D_
    color: red;_x000D_
}_x000D_
_x000D_
nav li.disabled:before {_x000D_
    content: '';_x000D_
    position: absolute;_x000D_
    top: 0;_x000D_
    left: 0;_x000D_
    bottom: 0;_x000D_
    right: 0;_x000D_
}
_x000D_
<nav>_x000D_
    <ul>_x000D_
    <li><a href="#">Link</a></li>_x000D_
    <li class="disabled"><a href="#">Link</a></li>_x000D_
    <li><a href="#">Link</a></li>_x000D_
    </ul>_x000D_
</nav>
_x000D_
_x000D_
_x000D_

JsFiddle - https://jsfiddle.net/grinmax_/9L1cckxu/


This may work

    ::selection {
        color: none;
        background: none;
    }
    /* For Mozilla Firefox */
    ::-moz-selection {
        color: none;
        background: none;
    }

With SASS (SCSS syntax)

You can do this with a mixin:

// Disable selection
@mixin disable-selection {
    -webkit-touch-callout: none; /* iOS Safari */
    -webkit-user-select: none;   /* Safari */
    -khtml-user-select: none;    /* Konqueror HTML */
    -moz-user-select: none;      /* Firefox */
    -ms-user-select: none;       /* Internet Explorer/Edge */
    user-select: none;           /* Non-prefixed version, currently supported by Chrome and Opera */
}

// No selectable element
.no-selectable {
    @include disable-selection;
}

In an HTML tag:

<div class="no-selectable">TRY TO HIGHLIGHT</div>

Try it in this CodePen.

If you are using an autoprefixer you can remove other prefixes.

Browser compatibility here.


Working

CSS:

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

This should work, but it won't work for the old browsers. There is a browser compatibility issue.


For those who have trouble achieving the same in the Android browser with the touch event, use:

html, body {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
    -webkit-tap-highlight-color: transparent;
}

UPDATE January, 2017:

According to Can I use, the user-select is currently supported in all browsers except Internet Explorer 9 and its earlier versions (but sadly still needs a vendor prefix).


These are all of the available correct CSS variations:

_x000D_
_x000D_
.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, Edge, Opera and Firefox */
}
_x000D_
<p>
  Selectable text.
</p>
<p class="noselect">
  Unselectable text.
</p>
_x000D_
_x000D_
_x000D_


Note that user-select is in standardization process (currently in a W3C working draft). It is not guaranteed to work everywhere and there might be differences in implementation among browsers. Also browsers can drop support for it in the future.


More information can be found in Mozilla Developer Network documentation.


Suppose there are two divs like this:

_x000D_
_x000D_
.second {_x000D_
  cursor: default;_x000D_
  user-select: none;_x000D_
  -webkit-user-select: none;_x000D_
  /* Chrome/Safari/Opera */_x000D_
  -moz-user-select: none;_x000D_
  /* Firefox */_x000D_
  -ms-user-select: none;_x000D_
  /* Internet Explorer/Edge */_x000D_
  -webkit-touch-callout: none;_x000D_
  /* iOS Safari */_x000D_
}
_x000D_
<div class="first">_x000D_
  This is my first div_x000D_
</div>_x000D_
_x000D_
<div class="second">_x000D_
  This is my second div_x000D_
</div>
_x000D_
_x000D_
_x000D_

Set cursor to default so that it will give a unselectable feel to the user.

Prefix need to be used to support it in all browsers. Without a prefix this may not work in all the answers.


In most browsers, this can be achieved using proprietary variations on the CSS user-select property, originally proposed and then abandoned in CSS 3 and now proposed in 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;
}

For Internet Explorer < 10 and Opera < 15, 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"));

Update 30 April 2014: This tree traversal needs to be rerun whenever a new element is added to the tree, but it seems from a comment by @Han that it is possible to avoid this by adding a mousedown event handler that sets unselectable on the target of the event. See http://jsbin.com/yagekiji/1 for details.


This still doesn't cover all possibilities. While it is impossible to initiate selections in unselectable elements, in some browsers (Internet Explorer and Firefox, for example) it's still impossible to prevent selections that start before and end after the unselectable element without making the whole document unselectable.


The right solution for CSS:

There's a bug without getting a resolver yet, so we can make use of it:

::-moz-selection {
}

::selection {
}

And voilà, there isn't any highlighting, but because of a bug, or a feature?

Here you have a demo, try to select text!!!


Try to insert these rows into the CSS and call the "disHighlight" at class property:

.disHighlight {
    user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    -webkit-touch-callout: none;
    -o-user-select: none;
    -moz-user-select: none;
}

You can use CSS or JavaScript for that.

The JavaScript way is supported in older browsers, like old versions of Internet Explorer as well, but if it's not your case, use the CSS way then:

HTML/JavaScript:

_x000D_
_x000D_
<html onselectstart='return false;'>_x000D_
  <body>_x000D_
    <h1>This is the Heading!</h1>_x000D_
    <p>And I'm the text, I won't be selected if you select me.</p>_x000D_
  </body>_x000D_
</html>
_x000D_
_x000D_
_x000D_

HTML/CSS:

_x000D_
_x000D_
.not-selectable {_x000D_
  -webkit-touch-callout: none;_x000D_
  -webkit-user-select: none;_x000D_
  -khtml-user-select: none;_x000D_
  -moz-user-select: none;_x000D_
  -ms-user-select: none;_x000D_
  user-select: none;_x000D_
}
_x000D_
<body class="not-selectable">_x000D_
  <h1>This is the Heading!</h1>_x000D_
  <p>And I'm the text, I won't be selected if you select me.</p>_x000D_
</body>
_x000D_
_x000D_
_x000D_


If you are using Less and Bootstrap you could write:

.user-select(none);

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to cross-browser

Show datalist labels but submit the actual value Stupid error: Failed to load resource: net::ERR_CACHE_MISS Click to call html How to Detect Browser Back Button event - Cross Browser How can I make window.showmodaldialog work in chrome 37? Cross-browser custom styling for file upload button Flexbox and Internet Explorer 11 (display:flex in <html>?) browser sessionStorage. share between tabs? How to know whether refresh button or browser back button is clicked in Firefox CSS Custom Dropdown Select that works across all browsers IE7+ FF Webkit

Examples related to highlight

Manually highlight selected text in Notepad++ jQuery "blinking highlight" effect on div? highlight the navigation menu for the current page Highlighting Text Color using Html.fromHtml() in Android? Changing the highlight color when selecting text in an HTML text input How to disable text selection highlighting Vim clear last search highlighting LaTeX package for syntax highlighting of code in various languages How do you make an element "flash" in jQuery How do you make Vim unhighlight what you searched for?

Examples related to textselection

Get the Highlighted/Selected text How do I disable text selection with CSS or JavaScript? How to make HTML Text unselectable How to disable text selection highlighting Is there a way to make text unselectable on an HTML page?