22

I am trying to prevent selection on an input field with the following considerations

  • Prevent selection using mouse
  • Prevent selection using keyboard (including Ctrl+A, shift+arrows)
  • Allow focusing into field using keyboard and mouse

So far I have tried these things:

CSS

I have attempted the using the following class

.unselectable {
  -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

Result: selection still possible

I have also tried below with no success:

$("#my_field").attr('unselectable','on')
     .css({'-moz-user-select':'-moz-none',
           '-moz-user-select':'none',
           '-o-user-select':'none',
           '-khtml-user-select':'none', 
           '-webkit-user-select':'none',
           '-ms-user-select':'none',
           'user-select':'none'
     }).bind('selectstart', function(){ return false; });

Javascript

I tried the below

$( "#my_field" ).select(function(e) {
        console.log("Select called");
        e.preventDefault();
});

Result: console printed the message, however the select still works

Thanks for your help

user2636664
  • 401
  • 1
  • 5
  • 14

5 Answers5

18

It can be done by setting the element's selectionStart to selectionEnd on select event:

var inp = document.getElementById('my_input');

inp.addEventListener('select', function() {
  this.selectionStart = this.selectionEnd;
}, false);
<input id="my_input" type="text" value="Try to select me!" />
Hashem Qolami
  • 97,268
  • 26
  • 150
  • 164
  • *Prevent selection using keyboard* —the above doesn't meet this criterion. Use tab to focus the field, which selects the entire content by default, so the value can then be copied. I don't know why anyone would want to do this anyway. – RobG Mar 23 '15 at 23:23
  • 1
    @RobG That's right, however we can do the same thing on `focus` event — http://jsbin.com/remihecomi/1/edit?js,output – Hashem Qolami Mar 23 '15 at 23:39
  • 3
    @HashemQolami—it's still possible to select the content by starting the selection from outside the element. And in any reasonably modern browser I can inspect the element and copy the content from the inspector. Really, this sort of stuff is pointless. – RobG Mar 24 '15 at 02:27
  • @HashemQolami Selection is also possible, when starting selection from inside the input and stopping outside. – Getter Jetter Oct 12 '18 at 07:59
  • @OlivierKrull I couldn't reproduce it. Can you provide an online example? – Hashem Qolami Oct 12 '18 at 08:40
  • @HashemQolami Well I just used your example above. I try to solve the same problem right now and I'm wondering if there is a cleaner solution (maybe css only) meanwhile? – Getter Jetter Oct 12 '18 at 08:42
  • @OlivierKrull Well, I cannot see the effect on Chrome/Ubuntu 16. However as RobG pointed out, this sort of things might be pointless as there will be always a way to get the content of an input and I just tried to give an answer to the OP's question at the time :) – Hashem Qolami Oct 12 '18 at 08:46
  • @HashemQolami of course I fully understand :-). I'm on Chrome => macOs High Sierra 10.13.6 – Getter Jetter Oct 12 '18 at 08:51
6

You can prevent the mousedown event to prevent the selection of the text inside the input.

<input type="text" id="unselectable" value="You can not select this text!"/>
<script>
document.getElementById("unselectable").addEventListener("mousedown", function(event){
  event.preventDefault();
});
</script>
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
5

You can cover over the <input> with any layer in absolute position, for example with div.wrapper::after or with other wrapper tag. Then use user-select: none for the wrapper tag (<div>, <label>, etc) and don't use user-select: none on the <input> itself.

But if your wrapper tag is <label> I recommend additionally adding the attribute readonly for the <input> and converting <label> to the block (or inline-block / flex / inline-flex).

input { outline: none; margin: 10px 0; width: 200px; }

.wrapper {
  position: relative;
  user-select: none;
}

.wrapper::after {
  content: '';
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

label.wrapper { display: block; }
<div class="wrapper">
  <input type="text" value="Any text in the div wrapper"/>
</div>

<label class="wrapper">
  <input type="text" value="Any text in the label wrapper" readonly />
</label>
kanstudio
  • 61
  • 1
  • 2
  • 1
    :D Thanks for the answer, I asked this more than 4 years ago. Hopefully, helps someone else – user2636664 May 13 '19 at 06:18
  • And even then: it sadly allows for selection using the keyboard (tab to highlight the input box, auto-selected on focus) – Igor Apr 13 '20 at 16:40
3

CSS-only solution:

This will not allow for input text to visually appear selected, while it is.
There are situations where this technique is good enough, if the developer do not care for the input's text to be able to be copy-pasted, but only the visual aspect of the selection is unwanted.

input{ color:transparent }
input::selection{ color:transparent }
<input value='invisible selection'>

It's also possible to use font-size:0 if width & height are defined on the input element.

JS Solution:

When the input gets focused → unfocus it (by calling the blur method):

<input value='unselectable selection' onfocus='this.blur()'>
vsync
  • 118,978
  • 58
  • 307
  • 400
1

This is the solution for when if you want pointer icon with cursor.

.input-select {
  position: relative;
  user-select: none;
  cursor: pointer;
}

.input-select::after {
  content: '';
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
<div class="input-select">
  <input type="text" value="any"/>
</div>
Irushan
  • 125
  • 2
  • 10