Back

Erstellen eines Copy-Buttons für Code-Blöcke

Erstellen eines Copy-Buttons für Code-Blöcke

Wenn Sie schon einmal beobachtet haben, wie jemand mühsam versucht, ein Code-Snippet manuell zu markieren und zu kopieren – oder es selbst erlebt haben –, wissen Sie bereits, warum ein Copy-Button für Code-Blöcke wichtig ist. Es ist ein kleines UI-Detail, das einen echten Unterschied macht, insbesondere für Nutzer, die mit Tastatur, Sprachbefehlen oder Touchscreens navigieren.

Dieser Artikel zeigt Ihnen Schritt für Schritt, wie Sie eine schlanke, zuverlässige UI zum Kopieren von Code-Snippets mit der modernen Clipboard API erstellen – ganz ohne externe Bibliotheken.

Wichtigste Erkenntnisse

  • Verwenden Sie navigator.clipboard.writeText() für eine moderne, Promise-basierte Kopier-Implementierung, die einen sicheren Kontext (HTTPS oder localhost) und ein vom Benutzer ausgelöstes Ereignis erfordert.
  • Extrahieren Sie Code mit textContent und nicht mit innerHTML, um zu vermeiden, dass <span>-Wrapper des Syntax-Highlighters zusammen mit dem eigentlichen Code kopiert werden.
  • Umschließen Sie den Aufruf mit einem try/catch-Block, um Berechtigungsfehler zu behandeln und den Benutzern klares visuelles Feedback zu geben.
  • Verbessern Sie die Barrierefreiheit, indem Sie dem Button ein aria-label hinzufügen, insbesondere wenn Symbole die Textbeschriftung ersetzen.
  • Das veraltete document.execCommand('copy') sollte nur als letztes Mittel für Legacy-Umgebungen verwendet werden.

Wie die writeText-Methode der Clipboard API funktioniert

Der moderne Ansatz zum Kopieren in die Zwischenablage in JavaScript ist navigator.clipboard.writeText(). Die Methode ist Promise-basiert, asynchron und wird von allen aktuellen Browsern unterstützt.

Zwei Dinge, die Sie vor der Verwendung wissen sollten:

  • Sie erfordert einen sicheren Kontext. Die Clipboard API funktioniert nur über HTTPS. Auf localhost wird auch reines HTTP als sicher behandelt, sodass dies für die Entwicklung in Ordnung ist.
  • Sie muss durch eine Benutzeraktion ausgelöst werden. Der Aufruf innerhalb eines click-Event-Handlers erfüllt diese Anforderung automatisch.
await navigator.clipboard.writeText("your text here");

Das ist der Kern des gesamten Features.


Text aus einem Code-Block extrahieren

Ihr HTML sieht wahrscheinlich ungefähr so aus:

<pre><code>const greeting = "hello";</code></pre>

Um den reinen Text zu erhalten, verwenden Sie textContent – nicht innerHTML. Mit innerHTML würden HTML-Tags zusammen mit dem Code kopiert, was niemals erwünscht ist.

const code = document.querySelector("pre code").textContent;

Wenn Ihre Code-Blöcke einen Syntax-Highlighter wie Prism.js oder Highlight.js verwenden, umschließt der Highlighter Tokens in <span>-Elementen. textContent entfernt all das und gibt nur den reinen Text zurück – genau das, was in der Zwischenablage des Benutzers landen sollte.


Den Copy-Button für Code-Blöcke erstellen

Hier ist eine vollständige, funktionierende Implementierung:

document.querySelectorAll("pre").forEach((block) => {
  const button = document.createElement("button");
  button.type = "button";
  button.textContent = "Copy";
  button.setAttribute("aria-label", "Copy code to clipboard");

  button.addEventListener("click", async () => {
    const code = block.querySelector("code")?.textContent ?? "";

    try {
      await navigator.clipboard.writeText(code);
      button.textContent = "Copied!";
      setTimeout(() => (button.textContent = "Copy"), 2000);
    } catch (err) {
      console.error("Copy failed:", err);
      button.textContent = "Failed";
      setTimeout(() => (button.textContent = "Copy"), 2000);
    }
  });

  block.style.position = "relative";
  block.appendChild(button);
});

Einige Punkte, die hier erwähnenswert sind:

  • aria-label gibt dem Button einen barrierefreien Namen für Screenreader, was besonders wichtig ist, wenn Sie den Text später durch ein Icon ersetzen.
  • e.currentTarget ist sicherer als e.target, wenn Ihr Button untergeordnete Elemente wie ein SVG-Icon enthält – e.target kann auf das Icon selbst statt auf den Button verweisen. (Sie können darauf zugreifen, indem Sie bei Bedarf den Parameter event zum Click-Handler hinzufügen.)
  • Der try/catch-Block behandelt Berechtigungsverweigerungen oder unerwartete Fehler elegant und gibt den Nutzern sichtbares Feedback statt eines stillen Fehlers.

Was ist mit älteren Browsern?

navigator.clipboard wird von modernen Browsern hervorragend unterstützt. Wenn Sie ältere Umgebungen unterstützen müssen, existiert document.execCommand('copy') als Fallback – ist jedoch veraltet und unzuverlässig. Verwenden Sie es nur als letzten Ausweg und mit einer Feature-Prüfung:

if (!navigator.clipboard) {
  // legacy fallback using document.execCommand('copy')
}

Für die meisten heute gebauten Dokumentationsseiten und Entwickler-Tools können Sie sich gefahrlos allein auf die Clipboard API verlassen.


Fazit

Ein funktionierender Copy-Button für Code-Blöcke läuft auf drei Dinge hinaus: Text mit textContent abgreifen, ihn mit navigator.clipboard.writeText() schreiben und dem Benutzer klares Feedback über Erfolg oder Misserfolg geben. Halten Sie den Button mit einem aria-label barrierefrei, behandeln Sie Fehler explizit, und Sie haben eine produktionsreife Implementierung in weniger als 30 Zeilen reinem JavaScript.

FAQs

Die Clipboard API erfordert einen sicheren Kontext, was in der Produktion HTTPS bedeutet. Browser behandeln localhost jedoch standardmäßig als sicher, sodass reines HTTP während der Entwicklung problemlos funktioniert. Wenn Sie auf einer lokalen Netzwerk-IP wie 192.168.x.x testen, wird die API fehlschlagen, da diese nicht als sicher gilt. Verwenden Sie stattdessen localhost oder richten Sie einen HTTPS-Dev-Server ein.

Nein. Die Clipboard API erfordert eine Benutzeraktivierung, das heißt, der Aufruf muss innerhalb eines vom Benutzer ausgelösten Event-Handlers erfolgen, wie etwa click, keydown oder pointerup. Der Aufruf von writeText beim Laden der Seite oder innerhalb eines setTimeout schlägt stillschweigend fehl oder löst einen Berechtigungsfehler aus. Diese Einschränkung verhindert, dass bösartige Seiten die Zwischenablage ohne Zustimmung kapern.

Die Eigenschaft textContent erhält Whitespace einschließlich Zeilenumbrüchen und Einrückungen bereits genau so, wie sie in Ihrem HTML geschrieben sind. Solange Ihre pre- und code-Elemente korrekt formatierten Quellcode enthalten, stimmt der kopierte Text überein. Vermeiden Sie die Verwendung von innerText, das Whitespace basierend auf dem CSS-Rendering normalisieren und browserübergreifend zu inkonsistenten Ergebnissen führen kann.

e.target verweist auf das Element, das den Klick tatsächlich empfangen hat, was ein untergeordnetes Element wie ein SVG-Icon innerhalb Ihres Buttons sein könnte. e.currentTarget verweist immer auf das Element, an das der Event-Listener angehängt wurde, in diesem Fall den Button selbst. Die Verwendung von currentTarget verhindert Fehler, wenn Benutzer auf verschachtelte Icons oder Spans innerhalb des Buttons klicken.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay