---
title:
  "Generating an image from an element and copying it to the clipboard using
  JavaScript"
description:
  "Learn how to generate an image from an element and copy it to the clipboard
  using native browser APIs that work in Safari and Chrome"
canonical_url: "https://www.bigbinary.com/blog/copy-generated-image-clipboard-javascript"
markdown_url: "https://www.bigbinary.com/blog/copy-generated-image-clipboard-javascript.md"
---

# Generating an image from an element and copying it to the clipboard using JavaScript

Learn how to generate an image from an element and copy it to the clipboard
using native browser APIs that work in Safari and Chrome

- Author: Rishi Mohan
- Published: December 22, 2021
- Categories: JavaScript

While most browsers support `navigator.clipboard.writeText` property which is
used to write a string to the clipboard, it gets a little tricky when you want
to copy an image to the clipboard. There's no common way to copy a blob image to
the clipboard for all browsers.

While working on an app that
[generates image from a tweet](https://kizie.co/tools/twitter-image) and lets
you save it, I wanted to add the ability to let users copy the image directly to
clipboard. The implementation seemed simple until I started working on it. The
problem is that browsers have different specs for writing a blob to the
clipboard.

In this article, we'll learn to write a function that generates an image from an
element and saves it in the clipboard. Also since browsers handle things
differently, we'll see how to copy an image to the clipboard work on Safari and
Chrome(and its variants).

## Things to know before we start

- Unfortunately, there's no way(or I haven't found one) to copy a blob image to
  clipboard in Firefox.
- There's no way to copy multiple images in one go.

## Creating an image from an element

Below is a function that utilises `domtoimage` library to return an image blob
from the element `screenshotRef.current`.

We can use `yarn add dom-to-image` to install the package.

Instead of `screenshotRef.current` used in the function, we can pass the `id` or
`className` of the element we want to generate the image from. More about how
domtoimage works can be learned [here](https://github.com/tsayen/dom-to-image).

```js
const snapshotCreator = () => {
  return new Promise((resolve, reject) => {
    try {
      const scale = window.devicePixelRatio;
      const element = screenshotRef.current; // You can use element's ID or Class here
      domtoimage
        .toBlob(element, {
          height: element.offsetHeight * scale,
          width: element.offsetWidth * scale,
          style: {
            transform: "scale(" + scale + ")",
            transformOrigin: "top left",
            width: element.offsetWidth + "px",
            height: element.offsetHeight + "px",
          },
        })
        .then(blob => {
          resolve(blob);
        });
    } catch (e) {
      reject(e);
    }
  });
};
```

## Copying an image to clipboard in Safari

First, we'll need a check to see if the browser is Safari. You can use below
check to detect Safari.

```js
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator?.userAgent);
```

Now that we have the check, we can use the function to copy the image to
clipboard.

```js
const copyImageToClipBoardSafari = () => {
  if(isSafari) {
    navigator.clipboard
      .write([
        new ClipboardItem({
          "image/png": new Promise(async (resolve, reject) => {
            try {
              const blob = await snapshotCreator();
              resolve(new Blob([blob], { type: "image/png" }));
            } catch (err) {
              reject(err);
            }
          }),
        }),
      ])
      .then(() =>
        // Success
      )
      .catch((err) =>
        // Error
        console.error("Error:", err)
      );
  }
}
```

We're using `navigation.clipboard.write` property to write an image blob to
clipboard. Inside it, we're creating a new ClipboardItem from the blob of the
element which is generated from `snapshotCreator()` function which we created in
first step.

## Copying an image to clipboard in other browsers

Since this method doesn't work in Firefox, we'll need a check to make sure we're
not running it on Firefox. Below condition takes care of that.

```js
const isNotFirefox = navigator.userAgent.indexOf("Firefox") < 0;
```

Now that we have the check, we'll use the same technique as we used for Safari,
but this time we'll need to ask the browser for the `navigator` permissions.

Below is the function that does that and then copies the blob image to the
clipboard in Chrome browser and its variants.

```js
const copyImageToClipBoardOtherBrowsers = () => {
  if (isNotFirefox) {
    navigator?.permissions
      ?.query({ name: "clipboard-write" })
      .then(async result => {
        if (result.state === "granted") {
          const type = "image/png";
          const blob = await snapshotCreator();
          let data = [new ClipboardItem({ [type]: blob })];
          navigator.clipboard
            .write(data)
            .then(() => {
              // Success
            })
            .catch(err => {
              // Error
              console.error("Error:", err);
            });
        }
      });
  } else {
    alert("Firefox does not support this functionality");
  }
};
```

The difference is not much except that Chrome and its variants require asking
for `navigator.permissions` before we can write the blob content to clipboard.
The above function uses the same `snapshotCreator()` function from the first
step to create an image from the element.

We can combine both the functions together to have this functionality work in
Safari and Chrome browser. You can check how it works on
[this page](https://kizie.co/tools/twitter-image), just click on "Copy Image"
button and then you'll be able paste the image anywhere.

## Links

- [Human page](https://www.bigbinary.com/blog/copy-generated-image-clipboard-javascript)
