Signatur
Beschreibung
Die Methode navigator.clipboard.write() ist der flexible Teil der asynchronen Clipboard-API. Anders als writeText(), das nur einfachen Text schreibt, nimmt write() ein Array von ClipboardItem-Objekten entgegen. Jedes davon kann dieselben Inhalte in mehreren MIME-Typen enthalten, etwa text/html und text/plain gleichzeitig. Die Zielanwendung sucht sich dann das passende Format aus.
Typische Einsätze sind Schaltflächen wie „Bild kopieren“ (PNG aus einem <canvas> oder von einer URL), „Als formatierten Text kopieren“ für Rich-Text-Editoren oder das Kopieren von Diagrammen und Tabellen. Offiziell garantiert sind nur text/plain, text/html und image/png. Chromium unterstützt zusätzlich eigene Formate mit dem Präfix web (z. B. "web application/json").
Die Methode funktioniert nur in einem sicheren Kontext (HTTPS oder localhost). Meist braucht sie außerdem eine vorübergehende Nutzeraktivierung, also einen direkten Klick oder Tastendruck. Die Werte eines ClipboardItem dürfen auch Promise<Blob> sein. So kann man den Schreibvorgang synchron im Klick-Handler starten, obwohl die Daten erst später geladen werden. Das ist besonders für Safari wichtig.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $data Pflicht | ClipboardItem[] | Array von ClipboardItem-Objekten. Jedes Objekt ordnet MIME-Typen Werten zu. Erlaubt sind Blob, string oder ein Promise, das zu einem davon auflöst. Die meisten Browser unterstützen derzeit nur ein Element im Array. |
Rückgabewert
undefined erfüllt wird, sobald die Daten in der Zwischenablage stehen. Es wird mit einer DOMException abgelehnt, z. B. NotAllowedError (keine Berechtigung, keine Nutzeraktivierung oder Dokument ohne Fokus) oder DataError bzw. NotAllowedError bei nicht unterstützten MIME-Typen.Beispiele
HTML und Klartext gleichzeitig kopieren
const copyRichText = async (html, text) => {
const item = new ClipboardItem({
'text/html': new Blob([html], { type: 'text/html' }),
'text/plain': new Blob([text], { type: 'text/plain' })
});
try {
await navigator.clipboard.write([item]);
console.log('Formatierter Text kopiert');
} catch (err) {
console.error('Kopieren fehlgeschlagen:', err.name);
}
};
document.querySelector('#copy').addEventListener('click', () => {
copyRichText('<strong>Hallo</strong> Welt', 'Hallo Welt');
});
Canvas-Inhalt als PNG-Bild kopieren
const canvas = document.querySelector('canvas');
const canvasToBlob = (cv) =>
new Promise((resolve) => cv.toBlob(resolve, 'image/png'));
document.querySelector('#copy-image').addEventListener('click', async () => {
const blob = await canvasToBlob(canvas);
await navigator.clipboard.write([
new ClipboardItem({ 'image/png': blob })
]);
console.log('Bild in Zwischenablage:', blob.size, 'Bytes');
});
Bild von URL kopieren – Safari-kompatibel mit Promise im ClipboardItem
document.querySelector('#copy-logo').addEventListener('click', async () => {
// Promise direkt übergeben, damit die Nutzeraktivierung nicht verfällt
const blobPromise = fetch('/img/logo.png').then((res) => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.blob();
});
try {
await navigator.clipboard.write([
new ClipboardItem({ 'image/png': blobPromise })
]);
console.log('Logo kopiert');
} catch (err) {
console.error(err);
}
});
Unterstützung prüfen und auf writeText zurückfallen
const copy = async (text, html) => {
if (navigator.clipboard?.write && typeof ClipboardItem !== 'undefined') {
const supportsHtml = ClipboardItem.supports?.('text/html') ?? true;
if (supportsHtml) {
await navigator.clipboard.write([
new ClipboardItem({
'text/html': new Blob([html], { type: 'text/html' }),
'text/plain': new Blob([text], { type: 'text/plain' })
})
]);
return 'rich';
}
}
await navigator.clipboard.writeText(text);
return 'plain';
};
document.querySelector('#btn').addEventListener('click', async () => {
console.log(await copy('Preis: 42 €', '<b>Preis:</b> 42 €'));
});
// Wichtig · Fallstricke
- Sicherer Kontext:
navigator.clipboardist nur über HTTPS oderlocalhostverfügbar. Überhttp://ist esundefined. - Nutzeraktivierung: Rufe die Methode direkt in einem Klick- oder Tastatur-Handler auf. Safari lehnt Aufrufe nach längeren
await-Ketten ab. Übergib dort einPromise<Blob>imClipboardItem, statt vorher zu warten. - Fokus: Hat das Dokument keinen Fokus (z. B. bei offenen DevTools), schlägt der Aufruf mit
NotAllowedErrorfehl. - Berechtigungen: Chromium kennt die Berechtigung
clipboard-write, die in aktiven Tabs automatisch erteilt wird. Firefox und Safari unterstützen diese Abfrage nicht. Verlasse dich also nicht aufnavigator.permissions.query(). - MIME-Typen: Verlässlich funktionieren nur
text/plain,text/htmlundimage/png. JPEG wird in der Regel abgelehnt, also vorher über ein Canvas in PNG umwandeln. MitClipboardItem.supports()(neuere Browser) lässt sich die Unterstützung prüfen. - Nur ein Element: Mehrere
ClipboardItems im Array werden von den meisten Browsern nicht unterstützt. - Sicherheit: Der Browser bereinigt HTML aus der Zwischenablage beim Einfügen. Trotzdem gilt: Wer Nutzereingaben als
text/htmlkopiert, sollte sie vorher sauber maskieren, denn die Zielanwendung könnte das HTML ungefiltert übernehmen. - Browser-Unterstützung: Firefox unterstützt
ClipboardItemundwrite()ohne Konfigurationsschalter erst ab Version 127. Ältere Browser brauchen eine Fallback-Lösung überwriteText()oder das veraltetedocument.execCommand('copy').