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:
- It’s weird to just put
-webkit-
for Firefox, even though it takes it - Edge doesn’t support
all
, but it supportsnone
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
- user-select on MDN – a bit more detail on here on the prefixes and properetary values.
- Can I Use on support – specifically of the none value
- Current version of spec – the best I can tell
- Document from Google with some interesting specifics on support and links to relevent bugs.
Whew
That was a lot of words for such a simple thing. Good work team.
I think you buried the lede! Stoked about non flash c&p.
Please don’t do this. It’s really annoying. If you want to “help” your users, just make a copy button or something.
Hate to call you out specifically, but I see dogmatic responses like this far too often. The only “never do this” appropriate on the web is “never say never do this.”
That’s OK. I personally find it very annoying and would personally prefer if people never did it. I can’t think of any use cases where overriding the expected selection interaction is particularly better than the normal interaction, but I’m open to being totally wrong on that. I just think it’s a bit presumptuous to force a user to interact a certain way when it’s pretty impossible to think of all the reasons why they might be selecting the text. That’s why I think the button is probably the best way to handle it. It’s totally opt-in.
I second this. I regularly want to grab only the embed URL from a video, on YouTube or Vimeo for example, so that I can drop it into a CMS field. Since I can’t select just a single part of it, I end up having to paste it into a text editor just to manipulate it.
The button idea would work well and from what I can tell would be much more explicit. Click here to copy, or here’s the text if you just need a part of it.
I have to agree with Tegan and Adam on this one, at least when it comes to
user-select: all
. I can’t think of any situation where you would know with 100% certainty that the user wants to select everything and not just a part of it.It’s extremely irritating when someone shares some code and requires you to select the entire block when all you need is a URL or something from it.
I’ll add myself to the list of those who don’t like automatic (and unavoidable) selection of the whole text. A lot of times I found myself wanting to copy only part of the text, and ending up saying: “Ugh, fine, I’ll paste it in a text editor and copy what I want!”
Forcing the selection of the whole content breaks the user’s expected behavior, so it’s a big “no” for me from the UX point of view.
Yes, with Google Maps I very often need only a certain part of the code but it’s always forcing me to copy the entire embed code, so I have to paste it into a text editor and then extract only the part I need.
So, user-select: all, apparently doesn’t work in Chrome? Just tried your demo in FF and works great, the line gets highlighted as selected. Chrome, nothin. I’m on windows, does that make a diff?
Second’d. I’m not seeing it working on Chrome 52.
Same here. Was disappointed as this seemed like a bone fide trick and one that could be useful.
Might be a flag thing? chrome://flags/
It works on Chrome 52 when about:flags/#enable-experimental-web-platform-features is on and without a flag in Chrome 54 Canary, at least.
Yep, the flag did it! But that is kinda sadface. :(
Hi. This example http://codepen.io/chriscoyier/pen/dXKxvv not working in Chrome 52.0.2743.116 (64-bit)
As mentioned above (but after your comment I believe) chrome://flags/ > Experimental Web Platform features or about:flags/#enable-experimental-web-platform-features will enable it in Chrome 52
I personally find that I often get annoyed by this because I am trying to select a specific part and it won’t work. Not sure if this is common but I wonder if it would be better to disable it on mousedown -> mouse drag and just have it work on click?
The other problem is I never know if this is going to be a feature or not and often only find out once I am halfway through my selection and then it has unexpected behaviour. Do you think there is any way we can indicate to users that this feature is active?
I like the concept of checking if they are selecting part. I think for most places I would use it, a small popover after selecting giving the option to select all
Woah, no! All the best screen readers read pseudo-element content now. As a web developer, you’re not supposed to put important content in pseudo-element because some screen readers don’t read it. But also don’t assume that it won’t get read.
(Also, on the main topic of the post. I don’t like the idea of forcing an “all” selection, but I’m okay with click-to-select and I definitely like the idea of being able to re-create a text-input-style “contain” behavior for select-all. Browsers, get on with supporting that option, OK?)
Thank you for saying this, Amelia. Was just about to post the same thing — that most current screen readers do read CSS generated content (and it should not be used as a way to hide content from them).
As for the text selection, if as an author you make it clear that an entire block of text will be selected and it is contextually appropriate, I think that is fine. I, too, hate trying to select a part of something only to have the entire thing selected every time.
Also, on this comment form, any chance the fields can have labels instead of placeholder only? Had to delete my email address to make sure it was not asking for URL instead.
I was under the impression that some screen readers (like Voice Over) read generated content but weren’t supposed to and thus were always kinda at risk for stopping doing that. I guess it moved the other direction.
Chris, it is going the other direction. A year ago Léonie Watson tracked support for generated content in screen readers and showed it was well supported. Since then support has only increased / improved. The reason is that many authors use generated content for something other than decoration, so ATs had to get on board with reading it.