Disabling Text Selection Highlighting with CSS

Abstract image used to represent Disabling Text Selection Highlighting with CSS

What was once a difficult problem for frontend developers to resolve, stopping users from being able to select text where they should not be able to (for example: inside of actionable elements such as buttons).

Now, with the widespread browser support, it is as simple as using user-select: none.

.classname {
  user-select: none;
}

The user-select property tells the browser whether text in the matched element can be selected. If you need the historical browser coverage discussed here, including Internet Explorer 10, include its -ms-user-select prefix as well as the other relevant prefixes:

.classname {
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

The only two gotchas to bear in mind here are:

  • Leave ordinary text inputs selectable. If a control needs custom selection behaviour, test that it can still receive focus and accept text on the iOS versions you support; selection handling should never make the control unusable.
  • Some manufacturers' versions of Android 4.0 (Ice Cream Sandwich) and below have been known not to work, although most do. These are devices released towards the end of 2011 so it is unlikely to be something you come across in any real user numbers.

The Old‑Fashioned Way

If the inability to select text is an absolute requirement for your project, and you still need to support Internet Explorer 9, or the very specific versions of Firefox that don't support the various browserprefixed permeations of user-select, then there is a sortof workaround that will get you part of the way there by using the ::selection pseudoelement:

.classname::selection {
  background: transparent;
}

/* For Firefox versions 2–61 without an autoprefixer,
   also include the moz prefix. */
.classname::-moz-selection {
  background: transparent;
}

Whilst this won't stop users from being able to highlight text on your website, what it will do is visually hide the fact that the text is being selected by setting the default browserblue to transparent instead.

In this case, do bear in mind that these two cannot be combined into a single ruleset because if the browser comes across what it considers an invalid selector whilst parsing the ruleset, it will discard the entire thing.

For a complete solution combining the two approaches (but not using an autoprefixer), your Sass might look a little like this:

.classname {
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
  user-select: none;

  &::selection {
    background: transparent;
  }

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

Fin.


Want to find out more?

If you need senior handson support with a complex React or Next.js platform, migration, performance issue, or technical SEO problem, send me the context and I'll tell you where I can help.