SVG support for the Async Clipboard API

The Clipboard interface of the Async Clipboard API provides read and write access to the contents of the system clipboard. This lets a web application implement cut, copy, and paste features. You can paste data from the clipboard into an application by calling the read() method, and copy data into the clipboard by calling the write() method. Apart from text, images in Portable Network Graphics (PNG) format, sanitized and unsanitized HTML, and Web custom formats, the Async Clipboard API now also supports copying and pasting SVG images, which means you can finally interact with image editing software that deals with SVGs more naturally by copying and pasting SVG images as images instead of as text or using hacky work arounds.

Feature detect SVG support

Detect support for SVG images (and any other MIME type) by calling the static ClipboardItem.supports() method, passing it the wanted MIME type.

const supportsSVG = () => {
  if (
    !('supports' in window.ClipboardItem) ||
    !window.ClipboardItem.supports('image/svg+xml')
  ) {
    return false;
  }
  return true;
};

Copy an SVG image

Copy an SVG image by populating the ClipboardItem with an object. The blob with the SVG image data is the value and the blob's type (that is, 'image/svg+xml' in this case) as its key.

copyButton.addEventListener('click', async () => {
  if (!supportsSVG()) {
    return;
  }
  try {
    const blob = await fetch(img.src).then((response) => response.blob());
    await navigator.clipboard.write([
      new window.ClipboardItem({
        [blob.type]: blob,
      }),
    ]);
  } catch (err) {
    console.error(err.name, err.message);
    alert(err.message);
  }
});

Paste an SVG image

To paste an SVG image, read the ClipboardItem back from the clipboard, and get the wanted type (that is, 'image/svg+xml' in this case) with the getType() method. This returns a blob that, once converted to a blob URL, you can assign to the src attribute of an <img>.

pasteButton.addEventListener('click', async () => {
  if (!supportsSVG()) {
    return;
  }
  const [clipboardItem] = await navigator.clipboard.read();
  const svgBlob = await clipboardItem.getType('image/svg+xml');
  if (!svgBlob) {
    alert('No SVG in the clipboard.');
    return;
  }
  const image = document.createElement('img');
  const blobURL = URL.createObjectURL(svgBlob);
  image.addEventListener('load', () => {
    URL.revokeObjectURL(blobURL);
  });
  image.src = blobURL;
});

Sanitization

SVG is a powerful format that, for example, allows embedded scripts. This can be dangerous when the user pastes content from unknown sources, so the browser runs a sanitization step. When data is copied, the Async Clipboard API produces a well-formed SVG document and then writes it to the clipboard. When data is pasted, a strictly processed SVG fragment is produced by the fragment parser. Therefore, before the paste operation, the onclick event handler attributes are still there, but upon pasting, they get removed.

Clipboard Viewer app on macOS inspecting the clipboard contents. It shows
that the onclick event listener attributes in the SVG are still there.
Clipboard Viewer app on macOS inspecting the clipboard contents. It shows that the onclick event listener attributes in the SVG are still there.

Demo

Explore copying and pasting SVGs in the demo on Glitch. View the source code to see how it works. Be sure to try clicking any of the circles before and after copying and pasting. After pasting, the potentially dangerous onclick event handler attributes are removed.

Acknowledgements

SVG support for the Async Clipboard API in Chromium was implemented by the Microsoft Edge team. This post was reviewed by Rachel Andrew and Anupam Snigdha.