How to implement "copy text" feature with the Clipboard browser API

This article was published on May 01, 2022, and takes approximately 3 minutes to read.

Copy and paste with vanilla JS used to be hard.

We had to rely on execCommand (a method that manipulates editable regions such as form input or contentEditable elements), but the "behind-the-scenes" implementation is cumbersome.

Copied
<input id="input" type="text" />
<button id="copy">Copy</button>

<script>
  function copy() {
    let copyText = document.querySelector("#input");
    copyText.select();
    document.execCommand("copy");
  }

  document.querySelector("#copy").addEventListener("click", copy);
</script>

If we don't want to have an input, we still need to have the input field there. So we need to hide the element using CSS.

Of course, it can go harder than that for more complex use cases.

That's why libraries like clipboard.js (which uses execCommand under the hood) were created. It eases the implementation and provides a much better API to have this capability.

execCommand is deprecated and will be removed from the web standards in the future.

Luckily time passes, and we have another native way to achieve this task: the Clipboard API.

This short post will show you how easy it is nowadays to implement this functionality in your website.

Before we start

It's essential that you understand the context you are in.

Do you need to support old browsers (really old ones)? Then probably this solution isn't the best for you. At the moment I'm writing this post, Internet Explorer doesn't support the API we're going to use, for example.

For ancient browser support, I'll always recommend clipboard.js.

The problem

Let's say you have a field on a website with a promo link.

Promo Link

To make our user's life easier when copying the content, we can have a button aside from the input to transfer the link to the clipboard with one click.

Promo link with copy button

Solution

The solution is a few lines of code.

For this example, I'm going to use vanilla JS, but the process will be the same in any other JS framework.

First, we need to listen for clicks in that button:

Copied
const copyLinkButtonElement = document.querySelector(".copyLinkButton");

copyLinkButtonElement.addEventListener("click", function copyPromoLink() {
  // Do stuff
});

Then, we need to get the input value:

Copied
const copyLinkButtonElement = document.querySelector(".copyLinkButton");
const inputElement = document.querySelector("#promoLink");
copyLinkButtonElement.addEventListener("click", function copyPromoLink() {
const promoLink = inputElement.value;
});

Finally, we call the writeText method from Clipboard API inside the navigator:

Copied
const copyLinkButtonElement = document.querySelector(".copyLinkButton");
const inputElement = document.querySelector("#promoLink");

copyLinkButtonElement.addEventListener("click", function copyPromoLink() {
  const promoLink = inputElement.value;
navigator.clipboard.writeText(promoLink);
});

And that's all.

You can go fancier and show somewhere a message, change the button color, or anything that indicates to the user that the promo link was copied successfully.

Here's a full demo

This solution will still be working if you even want to remove the input field and let only the copy button. Instead of getting the input field value, you'll need to pass the link URL directly to the writeText method and adapt the UI based on the design.

More about native Clipboard

As I previously said, deciding whether to use the new Clipboard API depends on your needs.

If you need to copy an image or rich text content, you need to use the clipboard.write method instead of clipboard.writeText, and this one isn't fully supported yet by all browsers.

If you're an extension author, you may need permission to read/write from the user's clipboard, which is not fully supported (yet).

Conclusion

Luckily this task has become much easier than before, at least for basic operations.

I strongly encourage you to read the clipboard API at MDNs and take a closer look at clipboard.js to understand when to use each one.

References