Copying text to clipboard with JavaScript

In this article, I will be explaining in depth how the _copyToClipboard_ snippet from 30 seconds of code works. You can find the source code for it and a ton of other useful methods in the project’s repository.

30 seconds of code: Javascript snippets that you can understand in 30 seconds or less
30 seconds of code: Javascript snippets that you can understand in 30 seconds or less

Core functionality

One thing that comes up quite often in website building is the ability to copy some text to clipboard, without the user selecting it or hitting the appropriate key combination on their keyboard. Javascript can easily do this in five short steps:

  1. Create a <textarea> element to be appended to the document. Set its value to the string that we want to copy to the clipboard.
  2. Append said <textarea> element to the current HTML document.
  3. Use HTMLInputElement.select() to select the contents of the <textarea> element.
  4. Use Document.execCommand('copy') to copy the contents of the <textarea> to the clipboard.
  5. Remove the <textarea> element from the document.

The simplest version of this method should look like this:

const copyToClipboard = str => {
const el = document.createElement('textarea');
el.value = str;
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
};
view raw copyToClipboard.js hosted with ❤ by GitHub

Bear in mind that this method will not work everywhere, but only as a result of a user action (like inside a click event listener), due to the way Document.execCommand() works.

Making the appended element invisible

If you try out the above method, you will probably see some flashing, when the <textarea> element is appended and then removed. This problem is especially bad for people on screenreaders, as it can cause some really annoying issues. So, the next logical step is to use some CSS to make this element invisible and make it readonly in case the users try to mess with it:

const copyToClipboard = str => {
const el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
};
view raw copyToClipboard.js hosted with ❤ by GitHub

Saving and restoring the original document’s selection

The final consideration is that the user might have already selected some content on the HTML document, so it would be nice to not remove anything they might have selected. Luckily, we can now use some modern Javascript methods and properties like [DocumentOrShadowRoot.getSelection()](https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/getSelection), [Selection.rangeCount](https://developer.mozilla.org/en-US/docs/Web/API/Selection/rangeCount), [Selection.getRangeAt()](https://developer.mozilla.org/en-US/docs/Web/API/Selection/getRangeAt), [Selection.removeAllRanges()](https://developer.mozilla.org/en-US/docs/Web/API/Selection/removeAllRanges) and [Selection.addRange()](https://developer.mozilla.org/en-US/docs/Web/API/Selection/addRange) to save and restore the original document selection. Here’s the final, annotated code implementing these improvements:

const copyToClipboard = str => {
const el = document.createElement('textarea'); // Create a <textarea> element
el.value = str; // Set its value to the string that you want copied
el.setAttribute('readonly', ''); // Make it readonly to be tamper-proof
el.style.position = 'absolute';
el.style.left = '-9999px'; // Move outside the screen to make it invisible
document.body.appendChild(el); // Append the <textarea> element to the HTML document
const selected =
document.getSelection().rangeCount > 0 // Check if there is any content selected previously
? document.getSelection().getRangeAt(0) // Store selection if found
: false; // Mark as false to know no selection existed before
el.select(); // Select the <textarea> content
document.execCommand('copy'); // Copy - only works as a result of a user action (e.g. click events)
document.body.removeChild(el); // Remove the <textarea> element
if (selected) { // If a selection existed before copying
document.getSelection().removeAllRanges(); // Unselect everything on the HTML document
document.getSelection().addRange(selected); // Restore the original selection
}
};
view raw copyToClipboard.js hosted with ❤ by GitHub

And that’s pretty much all there is to it. In less than 20 lines of code, we have created one of the most commonly needed methods in frontend development.