Signatur
Beschreibung
document.write() fügt Markup direkt in den Eingabestrom des HTML-Parsers ein. Während das Dokument noch geladen wird, z. B. in einem klassischen, synchronen <script>, landet der Text genau an der Stelle, an der das Skript steht. Der Parser verarbeitet ihn dann so, als hätte er von Anfang an im Quelltext gestanden.
Wird die Methode nach dem vollständigen Laden des Dokuments aufgerufen, etwa in einem Event-Handler oder nach DOMContentLoaded, ruft der Browser automatisch document.open() auf. Dabei wird das gesamte bestehende Dokument verworfen und durch den neuen Inhalt ersetzt. Das ist die häufigste Fehlerquelle bei dieser Methode.
Heute gilt document.write() als veraltete Technik. Sinnvoll ist sie praktisch nur noch, wenn man ein neues Dokument komplett von Grund auf erzeugt, z. B. in einem per window.open() geöffneten Fenster oder einem leeren <iframe>, zusammen mit document.open() und document.close(). Für das Einfügen von Inhalten in bestehende Seiten sollte man DOM-Methoden wie append(), insertAdjacentHTML() oder textContent verwenden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $...markup | string | TrustedHTML | Ein oder mehrere Strings bzw. TrustedHTML-Objekte. Sie werden ohne Trennzeichen hintereinander in den Dokumentenstrom geschrieben. Ist die Trusted-Types-CSP aktiv, werden nur TrustedHTML-Objekte akzeptiert. |
Rückgabewert
undefined).Beispiele
Druckansicht in neuem Fenster erzeugen
const druckeRechnung = (rechnung) => {
const fenster = window.open('', '_blank', 'width=600,height=800');
if (!fenster) return console.warn('Popup blockiert');
const doc = fenster.document;
doc.open();
doc.write('<!DOCTYPE html><html lang="de"><head><title>Rechnung</title></head><body>');
doc.write('<h1>Rechnung Nr. ', String(rechnung.nr), '</h1>');
doc.write('<p>Betrag: ', rechnung.betrag.toFixed(2), ' €</p>');
doc.write('</body></html>');
doc.close(); // Stream schließen, damit das Laden abgeschlossen wird
fenster.print();
};
druckeRechnung({ nr: 1042, betrag: 199.9 });
Leeres iframe komplett befüllen
const iframe = document.createElement('iframe');
document.body.append(iframe);
const idoc = iframe.contentDocument;
idoc.open();
idoc.write('<p style="font-family:sans-serif">Vorschau geladen</p>');
idoc.close();
console.log(idoc.body.textContent);
Fallstrick: Aufruf nach dem Laden löscht die Seite
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('#btn')?.addEventListener('click', () => {
// Implizites document.open(): der bisherige Inhalt wird verworfen!
document.write('<p>Hallo</p>');
document.close();
console.log(document.body.innerHTML);
});
});
// Besser: bestehendes DOM gezielt ergänzen
const hinweis = document.createElement('p');
hinweis.textContent = 'Hallo';
document.body.append(hinweis);
Mit Trusted Types absichern
// Voraussetzung: CSP "require-trusted-types-for 'script'"
const policy = trustedTypes.createPolicy('escape', {
createHTML: (s) => s.replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`)
});
const doc = window.open('', '_blank').document;
doc.open();
doc.write(policy.createHTML('<b>Benutzereingabe</b>'));
doc.close();
// Wichtig · Fallstricke
- Sicherheit (XSS):
document.write()interpretiert seine Argumente als HTML. Nicht bereinigte Benutzereingaben, URL-Parameter (location.search,location.hash) oder Daten auspostMessageführen direkt zu Cross-Site-Scripting. Eingeschleuste<script>-Tags werden ausgeführt. VerwendetextContentoder bereinige die Daten, z. B. mit DOMPurify oder über eine Trusted-Types-Policy. - CSP / Trusted Types: Mit
require-trusted-types-for 'script'in der Content Security Policy werfen reine Strings einenTypeError. Dann sind nur nochTrustedHTML-Objekte erlaubt. Geschriebene Inline-Skripte unterliegen zusätzlich derscript-src-Direktive. - Dokument wird überschrieben: Nach dem Laden ruft der Browser implizit
document.open()auf und ersetzt die ganze Seite. Mitdocument.close()abschließen, sonst zeigt der Browser weiter einen Ladezustand. - Performance: Chrome blockiert per
document.write()eingefügte, parserblockierende Fremd-Skripte bei langsamen 2G-Verbindungen. Synchrones Schreiben blockiert ohnehin den Parser und verzögert das Rendering. - Keine Wirkung / Fehler: In
async- oderdefer-Skripten sowie in Modul-Skripten wird der Aufruf ignoriert (mit Konsolen-Warnung). In XHTML-Dokumenten (application/xhtml+xml) wirft er eineInvalidStateError-DOMException. document.writeln()verhält sich genauso, hängt aber einen Zeilenumbruch an.