Javascript innerHTML: DOM-Elemente lesen und schreiben

innerHTML – Text und HTML-Tags direkt wie Text einsetzen und ersetzen

Jedes HTML-Element hat die Eigenschaft innerHTML, die sowohl Inhalt – einfachen Text als auch HTML-Tags – zwischen dem öffnenden und schließenden Tag des Elements lesen und schreiben kann. Nur Elemente ohne öffnendes und schließendes HTML-Tag haben kein innerHTML.

23-02-02 SITEMAP CSS HTML JS Basis JS Web Tutorial SVG

innerHTML – ersetzen, einfügen und löschen

innerHTML liest den Inhalt eines Elements und gibt ihn als String zurück (als Getter) oder schreibt einen String, der durchaus HTML-Tags enthalten kann, zwischen das öffnende und schließende Tag. Wenn innerHTML HTML-Tags enthält, wird die Zeichenkette als HTML geparst und die HTML-Tags werden zu HTML-Elementen und aus Sicht von Javascript zu Elementen des DOM.

<p id="elem">Alter Text</p>
…

const elem = document.getElementById("elem");
// liest den Inhalt eines Elements
const myText = elem.innerHTML; 
…
// überschreibt den Inhalt eines Elements
elem.innerHTML = "Text mit einem <a href="mylink.html" class="mylink">Link</a>.";

innerHTML setzt zwar einen String, aber wenn der String HTML-Tags enthält, werden die Tags im Dokument als Elemente interpretiert: Der String wird als HTML geparst. Der Link des Strings ist klickbar und die CSS-Klasse myLink wird auf den Link angewendet – das ist der Clou von innerHTML.

Elemente, die mit innerHTML eingesetzt wurden, sind in der Browser-Console sichtbar und Javascript hat Zugriff auf die Elemente.

Da IE heute keine Rolle mehr spielt, rutschen die Javascript-Methoden append()/prepend() in den Fokus: Sie hängen gleich mehrere Objekte und Textstrings mit einer Anweisung an den Anfang bzw. das Ende eines Elements.

innerHTML vs insertAdjacentHTML

Vielleicht doch lieber insertAdjacentHTML? Mit innerHTML werden alle Elemente innerhalb des Zielelements entfernt. insertAdjacentHTML fügt zusätzlichen Inhalt ein, aber berührt bereits existierende Elemente nicht.

<div class="demo foo">
	<a href="/javascript/array-static-methods.html">Hier lauert ein Link</a>
</div>
const elem = document.querySelector (".foo");
elem.innerHTML = "Neuer Text";

Um nur den Text, nicht aber u.U. enthaltene Elemente zu überschreiben, müsste der komplette Inhalt vor und nach dem zu einzusetzenden Text gesichert und erneut eingesetzt werden.

Dynamischer Inhalt und Sicherheit: textContent

Vertraue keinem externen Inhalt, über den du keine Kontrolle hast! Die modernen Browser unterstützen zusätzlich

  • outerHTML (überschreibt bzw. löscht auch das Element selbst mitsamt evtl. darauf liegenden Event Handlern),
  • InsertAdjacentHTML gezielt mit beforebegin, afterbegin, beforeend und afterend,
  • textContent (der eingesetzte String wird nicht als HTML geparst – sicherer und bei reinem Text auch effizienter als innerHTML).

Gerade weil innerHTML als Element geparst wird, ist der Ausführung auch ein Sicherheitsrisiko. Inhalte von externen Quellen sollten also niemals mit innerHTML eingesetzt werden, ohne sie vorher zu maskieren.

Besser und sicherer als mit innerHTML ist es, den Inhalt mit textContent zu übernehmen, denn textContent wird nicht als HTML geparst, sondern als reiner Text.

innerHTML: Inhalt löschen und einfügen

Wenn die Kontrolle beim Script selber liegt, ist innerHTML bezaubernd intuitiv. Die Anweisung

let myId = document.getElementById('myId').innerHTML;

liefert den vollständigen String zwischen den öffnenden und schließenden Tags des Elements mit der id myId.

innerHTML einfügen
Bezaubernd einfach
document.querySelector('#clear').onclick = function () {
   document.querySelector('#vanish').innerHTML = '';
}

Nahezu genauso einfach funktioniert der Setter mit innerHTML:

document.querySelector('#vanish').innerHTML = 
   '<img src="bird.svg" alt="" width="240" height="71" />' + 
   '<figcaption>Aus dem Hut gezogen</figcaption>';

Nahezu? Sobald Attribute mit inneren Hochkommas ins Spiel kommen, ist die Zeichenkette fehleranfällig.

Am Rande:Mit script type = text/template lassen sich lange Zeichenketten mit Hochkommas und +-Konkatenation sauber umgehen:

<script id="script-template" type="text/template">
   …
</script>

HTML Template im Script-Tag

innerHTML vs. createElement

Eigentlich klingt createElement ja akkurater und sauberer als innerHTML, auf den ersten Blick auch nach einer besseren Performance. Allerdings ist mehrfaches Einfügen in das DOM mehrfach aufwändiger als das einfache Einfügen eines Strings. Soll z.B. ein HTML-select-Element in ein Formular eingesetzt werden, müssen die option-Elemente ebenfalls eingehangen werden.

const select = document.createElement("select");
const option = document.createElement("option");
option.innerHTML = "Paris";
option.setAttribute("value","paris");
…

Aufeinanderfolgende createElement und appendChild- oder insertBefore-Anweisungen wirken nicht gerade elegant. Auf der anderen Seite zieht ein langer innerHTML-String mit mehreren Tags Fehler wie ein Magnet an.

const select = "<select name="city"><option value='berlin'>Berlin</option><option value='paris'>Paris</option></select>";
document.getElementById("form").innerHTML = select;

Für solche Aktion hält Javascript das documentFragment bereit, das außerhalb des DOM mit neuen Elementen bestückt und erst dann ins DOM gehangen wird, wenn alle Elemente sozusagen backstage vorbereitet wurden.