Have you ever tried to copy and paste some text only to find it frustrating, awkward, or even impossible? I bet you have. It’s not random. On the web, you have a decent amount of control over it. Let’s just lay a bunch of stuff out there as food for thought.
Not Actually Text
Perhaps this is the most obvious problem, so let’s not dwell on it. If text can be “real text” on the web, please do that. Compared to an image of text, real text is more accessible, more indexable, and more useful. You can select it to copy and paste!
Accidental Overlaps
Have you ever seen that effect where text fades out at the bottom? It’s often done by laying a gradient image over top of that text. You can see through part of it, but that element is still sitting on top of the text, meaning mouse interaction happens on the overlap, not the text.
In this demo, the overlap is a pseudo element filled with a a gradient and positioned on top. Thankfully, this is largely a fixable situation. pointer-events: none;
on the overlap will go a long way in helping. With that set, pointer interactions will totally ignore the element. Clicks will go right through as if it wasn’t even there.
That’s great, except IE 10 doesn’t support pointer-events. If you still wanted to rely on that, Modernizr v3 has a test for it, so you could only apply the overlay if you knew pointer-events worked.
Or, instead of an overlay at all, you could color individual lines to make it look like a fadeout as we covered in this article.
The Post-Selection Popup
Some sites make some pretty big assumptions after you’ve selected some text. A common one is: OH GOOD YES HELLO HI I SEE YOU OBVIOUSLY MUST WANT TO SHARE THIS BIT OF TEXT ON SOCIAL MEDIA LET ME HELP. Not everyone is a fan. Aside from being presumptuous and over-eager, it can get in the way of screenshotting.
Highlighter.js is a library that makes this all-too-easy.
CSS Control Over Selectability
There is actually a CSS property specifically for controlling the selectability of text: user-select
.
.unselectable {
-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 */
}
Aside from a few browser quirks, text with that set is unselectable. That can be pretty useful when trying to design better UX around the selectability of text on your site.
On mobile, text selection in generally done by a long tap which brings up some text selection choices. You can prevent that “callout” (and thus prevent the selection of text), with:
-webkit-touch-callout: default /* displays the callout */
-webkit-touch-callout: none /* disables the callout */
Other visible text that doesn’t copy
You can force text to be unselectable with the CSS above, but some text isn’t selectable automatically:
- Default counters, like the bullets from unordered lists or the numbers from ordered lists
- Custom CSS counters
- Pseudo element text
Accidentally Selecting Line Numbers
Once in a while you’ll run across a chunk of code on a website you want to copy and paste. After you paste it, you find the line numbers came along with it.
It’s kind of surprising actually, since it seems like you’d have to go out of you way to make that happen. Knowing what we know now, those line numbers could have used CSS to prevent them from being copied. Or the code could have been marked up as a list to show the numbers that won’t copy. Or it could have used custom counters which wouldn’t copy. Or pseudo elements before the lines that wouldn’t copy (relevant article).
So the only way this can happen is if they just plopped some text right in the element at the start of the line and did nothing to prevent it from being copied. Likely a pretty easy fix we could encourage any offender to do.
Selecting (All) Text with JavaScript
Form elements are often used for this. If you want to provide some text that is specifically for copy-and-pasting, you typically put it in an input
or textarea
.
<textarea id="ta">a bunch of text</textarea>
Then it’s really easy to select that text programmatically:
var ta = document.getElementById("ta");
ta.focus();
ta.select();
You can’t really do that on a
or whatever. Also, if a user is inside a form element, the typical “Select All” command will only select the text within the bounds of that element, which is nice, expected behavior.
If you want the behavior where the text gets selected as you click into it, here’s a pretty succinct jQuery way to do it:
$('#ta').on("focus", function(e) {
e.target.select();
$(e.target).one('mouseup', function(e) {
e.preventDefault();
});
});
That bit with the mouseup
allows the text to remain selected after the mouseup event. Normally the mouseup will deselect the text and activate the cursor.
I like this way because it also doesn’t force all the text to be selected no matter what (which people don’t like), just on the inital focus. So after the focus, if you want to change the selection yourself and only copy a part of the text, you can do that.
If you don’t provide click-to-select, that sometimes makes people unhappy too, so it’s a balance. Hence why I like the focus-to-select, then let it be approach above.
There is a lot more to know about selecting text with JavaScript, including Range selection and stuff, which is pretty complicated and best saved for another article.
Copying to the Clipboard Programmatically
This ability just recently surfaced in JavaScript. At the time of this writing, just Chrome and IE. It’s done through document.execCommand('copy');
There is a whole history here that I’m not quite up-to-snuff with. I think it was largely a security concern that was why it was impossible in JavaScript. Not to mention a tastefulness concern (who wants to visit a site only to find their clipboard messed with?). For whatever reason, it’s available again.
Matt Gaunt offers some example code:
Email me at [email protected]
var copyEmailBtn = document.querySelector('.js-emailcopybtn');
copyEmailBtn.addEventListener('click', function(event) {
// Select the email link anchor text
var emailLink = document.querySelector('.js-emaillink');
var range = document.createRange();
range.selectNode(emailLink);
window.getSelection().addRange(range);
try {
// Now that we've selected the anchor text, execute the copy command
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copy email command was ' + msg);
} catch(err) {
console.log('Oops, unable to copy');
}
// Remove the selections - NOTE: Should use
// removeRange(range) when it is supported
window.getSelection().removeAllRanges();
});
Copying text to the clipboard programmatically has always been a desire though. We used to have to use flash, typically a library called ZeroClipboard. Here’s a David Walsh tutorial on that.
How To Paste With/Without Style/Formatting
When you copy text, it generally comes along with formatting.
On Macs, there is a Paste and Match Style command though, which can be very useful to get rid of that formatting when you don’t want it. Like when pasting into an email. Command-Shift-V is the usual shortcut for that.
I generally prefer this behavior, so I did the thing where I mapped it to Command-V (overriding normal paste).
You can still paste which formatting through the menus if you need to.
Extra Crap on the Clipboard
Have you ever selected some text from a site, only to find when you paste it that it has happened some extra crap to the end of your selection? READ MORE AT FART-KNUCKLE.BUSINESS!!!
Awkward Retained Capitalization
You can capitalize text in CSS with text-transform: uppercase;
. It causes a rather large (annoying) functionality difference in copy-pasting though across browsers.
From what I tested quickly:
- Firefox and IE respect the original text (what is in the DOM).
- Chrome, Safari, Opera, and iOS respect the CSS capitalization.
I prefer the former.
Block Links Can Make It Harder To Copy
In HTML5, we learned we can now wrap anchor tags around whatever we want. Even though they are inline elements, we can wrap them around blocks without worry of being invalid. It doesn’t come without repercussion though.
Title
This makes the entire block title a link without any CSS assistance, but it does make the title a bit harder to copy. Wrapping that markup around and doing h3 > a { display: block; }
makes it a little easier, assuming there is a bit of padding on the h3, because then you can start the selection in the padding and move.
So on one hand there is a larger click area, and on another it’s slightly harder to copy (if you’re a normal right-to-left copier). Your call.
See the Pen Block titles kinda hard to copy by Chris Coyier (@chriscoyier) on CodePen.
Sometimes block structure itself can cause annoying situations. Like here, you’re trying to select a movie title, but a pixel too far and you get a bunch of weird text in totally unrelated positions:
It’s not that huge of an issue here as I think people are a bit used to this and know how to back off and get what they need. But it’s worth considering. Even things like flexbox ordering can totally change how text selection behaves even when visually things look identical.
See the Pen flex ordering and selection by Chris Coyier (@chriscoyier) on CodePen.
Pasting into the Console
Classic rube mistake: Copying the “$ ” at the beginning of console commands in blog posts about how to do terminal things. HANDS UP people. Just me? Dammit. Anyway. There is a pretty funny dotfile thing to warn you when you do it.
Any more?
Have any pet peeves about copy and paste, or selection in general, on the web?
Another note on text in pseudo elements: They’re not searchable on the page (⌘-f), which is an accessibility concern too, depending on the situation.
The auto-selection happens on mouseup, so you can copy parts of text by keeping the button pressed and hit ⌘C
I’m a fan of double-click to select all text, depending on the context.
I know some people think double-click (and triple-click) is bad UX, but… meh.
Selecting the whole text in Javascript is the worst thing ever. It’s really unbelievable that someone is happy with that.
“There is actually a CSS property specifically for controlling the selectability of text: user-select.”
Oh, goodie. More CSS to be abused to the nth degree whilst futilely attempting to ‘save’ one’s Intellectual Property from the child plagiarists to the detriment of those who just want to file away a link with a paragraph to remind them of what interesting content there was behind that silly domain name.
I completely agree. The legit user case when one wants to prevent selection of UI elements is very narrow, while that CSS property can be abused in any possible way.
It’s sometimes nice to use user-select:none; on custom div buttons since it prevents the text inside the button from getting selected when the user double clicks it.
That’s the only time I’ve used it at least.
It’s actually a life saver on all kinds of pop-up images (depending on how you want them to close), when your user can accidentally select an image without being able to reliably unselect it; this way they won’t get them overlayed in blue and you can copy/manipulate images reliably in other ways, like by right-clicking.
It’s also handfull for kiosk mode on touchable screens. To prevent text selecting when user miss a button.
Other visible text that doesn’t copy:
<input disabled>
and<textarea disabled>
in Firefox don’t allow you to select or copy the text.Is pretty annoying try to copy data in a form with locked fields.
<input readonly>
allows selection and copying, though.“IE 10 doesn’t support pointer-events”
I’m pretty sure I once found a workaround for this in an earlier version of IE with the use of SVG.. I would try to remember but it’s late and I should be in bed :P
Nice write up, real comprehensive.
Quick typo..
$(e.target).one(‘mouseup’, function(e) {
Should be .on(…)
No typo.
http://api.jquery.com/one/
You can get around the site select all the text when you only want a bit by hitting ctrl + c before mouseup.
Hi Chris
You could also set the normal paste shortcut to CMD + SIHFT + V. So you don’t even need the menu. ;)
Marc
Keep in mind, you can create multiple selection in Firefox. With
ctrl
/cmd
+ selectionAnyone have an opinions on what the best web based WYSIWYG editor is for dealing with copy and pasting content?
Anyone have an opinions on what the best web based WYSIWYG editor is for dealing with copy and pasting content?
Please
We’re building one at copycopy.com
On OSX you can use CMD+Shift+alt+v to paste without formatting in every App.
To your point about text-transform and copying capitalized letters, I also prefer the Firefox/IE method of copying the source text, not the styled text. I’ve ranted about this: http://rosel.li/060612
I also think the WebKit-based browsers are running against the spec by copying the capitalized text: “This property transforms text for styling purposes. (It has no effect on the underlying content.)” Spec: http://www.w3.org/TR/css-text-3/#text-transform
I read that to mean the underlying content (which I am copying) should not be changed (which it is by transforming it).
“things like flexbox ordering can totally change how text selection behaves even when visually things look identical.”
This could create serious accessibility issues, since the reading sequence is changed and, if you have focusable elements, the tab order is different from the reading order / listings (for example, the list of buttons follows the DOM, while the Tab order follows visual order).
Yaa., you can also double click a word to select it.