How to disable text selection highlighting?

anon Source

For anchors that act like buttons (for example, Questions, Tags, Users, etc. at 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 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?

csscross-browserhighlightingtextselection

Answers

answered 9 years ago X-Istence #1

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.

answered 9 years ago hbw #2

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.

answered 9 years ago seanmonstar #3

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

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

answered 9 years ago Pekka 웃 #4

A JavaScript solution for IE is

onselectstart="return false;"

answered 8 years ago Tim Down #5

In most browsers, this can be achieved using proprietary variations on the CSS user-select property, originally proposed and then abandoned in CSS3 and now proposed in CSS UI Level 4:

*.unselectable {
   -moz-user-select: 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 < 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 re-run 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 (IE 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.

answered 8 years ago Blowsie #6

UPDATE January, 2017:

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


All of the correct CSS variations are:

.noselect {
  -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 */
}
<p>
  Selectable text.
</p>
<p class="noselect">
  Unselectable text.
</p>


Note that it's a non-standard feature (i.e. not a part of any specification). It is not guaranteed to work everywhere, and there might be differences in implementation among browsers and in the future browsers can drop support for it.


More information can be found in Mozilla Developer Network documentation.

answered 7 years ago Benjamin Crouzier #7

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;
}

answered 7 years ago Alex #8

Workaround for WebKit:

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

I found it in a CardFlip example.

answered 7 years ago Tom Auger #9

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;
    -o-user-select: none;
    -ms-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: IE9 may not need this extra jQuery piece, so you may want to add a version check in there.

answered 6 years ago Codler #10

If you are using Less and Bootstrap you could write:

.user-select(none);

answered 6 years ago Gaurang #11

-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');

answered 6 years ago Chase1986 #12

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

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

answered 5 years ago karthipan raj #13

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.

answered 5 years ago Automatico #14

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

jQuery UI Disable Selection:

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

answered 5 years ago Ale #15

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

It's not the best way, though.

answered 5 years ago Elad Shechter #16

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;/*IE*/
}

answered 5 years ago zgnilec #17

Check my solution without JavaScript:

jsFiddle

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

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

answered 5 years ago suraj rawat #18

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 be working, but it won't work for the old browsers. There is a browser compatibility issue.

answered 5 years ago Suraj Naik #19

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

answered 4 years ago r3wt #20

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.

answered 4 years ago Beep.exe #21

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;
}

answered 4 years ago Luke Madhanga #22

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.

answered 3 years ago SemanticZen #23

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; 
}

answered 3 years ago ZECTBynmo #24

In the above solutions 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:

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

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

answered 3 years ago mustafa-elhelbawy #25

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;
}

answered 2 years ago Gaurav Aggarwal #26

Suppose there are two div like this

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

<div class="second">
  This is my second div
</div>

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

Prefix need to be use to support it in all browsers without prefix this may not work in all the answers.

answered 2 years ago Mohammed Javed #27

I have learned from CSS-Tricks website.

user-select: none;

And this also:

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

answered 2 years ago Hetal Rupareliya #28

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

answered 2 years ago Pushp Singh #29

This highlighting effect is due to the action called hover(onMouseHover). When you will hover on any tab it's color will be changed. Just say for example.

<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 give any color if you wanted to get it highlighted, else yo u can give none.

answered 2 years ago user1012506 #30

Try insert this rows to CSSand call the "disHighlight" at class proprty:

.disHighlight{
    user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    -webkit-touch-callout: none;
    cursor: default;
    -khtml-user-select: none;
    -moz-user-select: none;
}

answered 2 years ago Chirag Dave #31

You can use User-select property as below for that..

p {  
     -webkit-user-select: none;  /* Chrome all / Safari all */
     -moz-user-select: none;     /* Firefox all */
     -ms-user-select: none;      /* IE 10+ */
      user-select: none;          /* Likely future */             
   }

Link for the Detailed Description

answered 2 years ago grinmax #32

Maybe you can use this solution throught :before

nav li {
	display: inline-block;
	position: relative;
}

nav li a {
	display: inline-block;
	padding: 10px 20px;
}

nav li a:hover {
	color: red;
}

nav li.disabled:before {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	bottom: 0;
	right: 0;
}
<nav>
	<ul>
	<li><a href="#">Link</a></li>
	<li class="disabled"><a href="#">Link</a></li>
	<li><a href="#">Link</a></li>
	</ul>
</nav>

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

answered 1 year ago Alireza #33

You can use CSS or JavaScript for that, JavaScript way is supported in Older browsers like Old IEs as well, but if it's not your case, use the CSS way then:

HTML/JavaScript:

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

HTML/CSS:

.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;
}
<body class="not-selectable">
  <h1>This is the Heading!</h1>
  <p>And I'm the text, I won't be selected if you select me.</p>
</body>

answered 8 months ago Yevgeniy Afanasyev #34

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);
}

answered 8 months ago oMiKeY #35

I combined the various browser css with the unselectable tag required for IE < 9.

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

answered 6 months ago KAZ #36

Quick hack update: March 2017 -from CSS-Tricks

If you put the value 'none' for all the CSS user select attributes as showed in below, 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;  /* IE 10+ */
   user-select: none;  /* Likely future */ 
}

As CSS-Trick says the problems is

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

So you can also use the below one instead to enforce that an entire element getting selected which is the solution for the problem. All you have to do is changing the value 'none' to 'all' which would look like this

.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 */   
}

answered 5 months ago jasonleonhard #37

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 */
  }

comments powered by Disqus