Force Selection of Text Block

Avatar of Chris Coyier
Chris Coyier on

📣 Freelancers, Developers, and Part-Time Agency Owners: Kickstart Your Own Digital Agency with UACADEMY Launch by UGURUS 📣

Have you ever seen (or put yourself) some text into a <textarea> or <input>, not because it was part of a form, but because it made the whole block of text easier to select. Inputs like that have selection boundaries, meaning you can click into them and (for example) Select All and get just the text inside the input.

There is a CSS property that allows us to do that without needing to use a not-particularly-semantically-appropriate form input.

It’s the user-select property, and it works like this:

.force-select-all {
  user-select: all;
}

Autoprefixer will handle this for you, but if doing by hand, this is what you’ll need for the best browser support:

.force-select-all {
  -webkit-user-select: all; /* Covers Blink-land & Firefox (yup) */
  user-select: all; /* Someday */
}

An example, you ask?

I find the most common use-case for this kind of thing is “here’s some server-generated copy-and-pasteable embed code for Our Thing™”. Imagine the embed code for YouTube or Vimeo videos:

Makes sense on a site like my old HTML-Ipsum, which is in dire need of an update.

A demo

How about a slightly different use-case, a cheat sheet, in which there are some simple code snippets that are intended to be copied:

See the Pen SVG Shape Cheatsheet (user-select: all; demo) by Chris Coyier (@chriscoyier) on CodePen.

More on the prefixing thing

Actually, Autoprefixer will give you:

.force-select-all {
  -webkit-user-select: all;
  -moz-user-select: all;
  -ms-user-select: all;
  user-select: all;
}

Which is understandable because:

  1. It’s weird to just put -webkit- for Firefox, even though it takes it
  2. Edge doesn’t support all, but it supports none with a prefix, so it always prefixes the property

Let’s say you don’t like the forced selection, but like the selection boundaries.

That’s what the contain value is all about. It makes text selection behave like it would within an input:

.select-text-like-you-would-within-a-textarea {
  /* Not supported anywhere yet */
  user-select: contain;
}

Alas, no support yet. IE/Edge does support a proprietary version though:

.ie-version-of-contain {
  -ms-user-select: element;
}

So now we have none, all, and contain. There is also text, which makes the text selectable like “normal” text.

If you ever need to reset the value, you should use auto, as it’s the value that returns the element back to it’s normal state (e.g. a <p> would return to text, a <textarea> would return to contain).

Styling selected text

Since we’re talking about selecting text here, remember you can style selected text:

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

Although… I might recommend not pairing these, as the auto-selecting text behavior is already a little weird, so that combined with a totally different selection style might be confusing to the point of a person not understanding what is happening.

Or at least, making the ::selection site-wide, not specific to isolated areas.

The Classic JavaScript Way

No Edge support might be a deal-breaker for you. If it’s mission-critical to auto-select text, you might wanna just stick with an input and JavaScript.

Super basic example:

See the Pen Simplest Select by Chris Coyier (@chriscoyier) on CodePen.

I’m sure you could get a lot fancier, like by avoiding inline event handling, and considering the “OK, I’ve clicked into you and you selected your text, I get it, now stop doing that so I can only select a part of you” – which is certainly possible.

Pseudos

For better or worse, user-select: text; might be a way to make pseudo elements (like ::before or ::after) selectable, which they currently are not in any browser. It’s probably good that you can’t select them, as pseudo elements also aren’t supposed to be read in AT (because they aren’t “content”). But it is kinda strange to see text on a screen you can’t select, so I wouldn’t be surprised whichever way browsers land on this.

Mobile

For iOS, there is yet-another thing you may want to use:

.prevent-touch-callout {
  -webkit-touch-callout: none;
}

Not specifically about selection, but if you’re preventing selection of text you’re likely preventing interaction in general. MDN:

When a target is touched and held on iPhone OS, Safari displays a callout information about the link. This property allows disabling that behavior.

Forcing a copy?

Since we’re talking about forcing selection of text, can we force a copy-to-clipboard as well? You can, actually. There used to be a Flash-based way to do it, but, as I think we all know, Flash is pretty dead. Chrome just announced another deathblow. IE 10 supported this execCommand thing, and as it happens, that seems like the thing that browsers are going with. Snagged this demo from that Google article by Matt Gaunt:

See the Pen Copy Text with a Button (Google Example) by Chris Coyier (@chriscoyier) on CodePen.

Looks like that works in Blink-land, Firefox, and Edge, so… cool.

More information

Whew

That was a lot of words for such a simple thing. Good work team.