<script>

Zuletzt aktualisiert am 3. Juli 2026

Das <script>-Element bringt Interaktivität in deine Webseite. Damit bindest du JavaScript-Code ein, entweder direkt in der HTML-Datei oder als externe Datei. Script-Tags sind das Fundament für alles, was über statischen Content hinausgeht: Animationen, Formulare, dynamische Inhalte und vieles mehr.

Grundlagen

Mit dem <script>-Element hast du zwei Möglichkeiten: Du kannst externe JavaScript-Dateien über das src-Attribut einbinden oder Inline-Code direkt zwischen die öffnenden und schließenden Tags schreiben.

Externe Scripts sind die sauberste Lösung. Der Code liegt in separaten .js-Dateien, die der Browser cachen kann. Das macht deine HTML-Dateien übersichtlicher und die Seite lädt schneller beim nächsten Besuch.

Inline-Scripts schreibst du direkt in die HTML-Datei. Das ist praktisch für kleine Code-Schnipsel oder wenn du serverseitige Daten direkt in JavaScript übergeben willst. Bei größeren Projekten wird es damit aber schnell unübersichtlich.

Die Platzierung des Script-Tags ist wichtig. Früher hat man Scripts oft im <head> platziert, aber das hat ein Problem: Der Browser stoppt das Parsen des HTML, lädt und führt das Script aus, und erst dann geht’s weiter. Das verzögert die Anzeige der Seite.

Deswegen sieht man heute meist Script-Tags am Ende des <body>, kurz vor dem schließenden Tag. Dann ist das DOM schon fertig geparst und das Script kann direkt damit arbeiten.

Noch besser: Du nutzt defer oder async. Diese Attribute lösen das Blocking-Problem elegant. Der Browser lädt das Script parallel zum Parsen des HTML, und du entscheidest, wann es ausgeführt wird. Mit defer wartet das Script, bis das DOM fertig ist. Mit async startet es sofort nach dem Download.

Syntax

<!-- Externes Script -->
<script src="pfad/zur/datei.js"></script>

<!-- Inline-Script -->
<script>
  console.log("Hallo Welt");
</script>

Attribute

Attribut Typ Beschreibung Beispiel
src URL Pfad zur externen JavaScript-Datei src="script.js"
type String MIME-Type des Scripts. Standardwert ist text/javascript. Mit module aktivierst du ES6-Module type="module"
defer Boolean Script wird parallel geladen, aber erst nach dem DOM-Parsing ausgeführt. Nur für externe Scripts defer
async Boolean Script wird parallel geladen und sofort nach Download ausgeführt. Nur für externe Scripts async
crossorigin String Steuert CORS-Verhalten für externe Scripts. Werte: anonymous oder use-credentials crossorigin="anonymous"
integrity String Hash zur Überprüfung der Script-Integrität (Subresource Integrity). Schützt vor manipulierten Dateien integrity="sha384-..."
nomodule Boolean Script wird nur in älteren Browsern ausgeführt, die keine ES6-Module unterstützen nomodule
fetchpriority String Ladepriorität des Scripts: high, low oder auto. Steuert, wie dringend der Browser die Datei herunterlädt fetchpriority="high"

Ladeverhalten im Vergleich

VarianteLadenAusführungDOM-ZugriffReihenfolge
Normal (kein Attribut)Blockiert ParsingSofortNur wenn danach im DOMGarantiert
deferParallelNach DOM-ParsingGarantiertGarantiert
asyncParallelSofort nach DownloadNicht garantiertZufällig
type=“module”ParallelNach DOM-Parsing (wie defer)GarantiertGarantiert

Normal blockiert das Parsing komplett. Der Browser wartet, bis das Script geladen und ausgeführt ist. Das ist langsam und out-dated.

defer ist perfekt für Scripts, die mit dem DOM arbeiten. Sie laden parallel, aber die Ausführung wartet brav, bis das HTML fertig geparst ist. Mehrere defer-Scripts behalten ihre Reihenfolge.

async ist für unabhängige Scripts gedacht: Analytics, Ads, Third-Party-Tools. Sie laden parallel und starten sofort, wenn sie fertig sind. Die Reihenfolge ist nicht garantiert.

type=“module” aktiviert ES6-Module mit Import/Export. Diese Scripts verhalten sich automatisch wie defer: laden parallel, warten auf das DOM, behalten die Reihenfolge.

Ladepriorität mit fetchpriority

Zusätzlich zu defer und async kannst du mit fetchpriority die Ladepriorität steuern. Das Attribut ändert nicht, wann ein Script ausgeführt wird, sondern wie dringend der Browser die Datei im Vergleich zu anderen Ressourcen herunterlädt. Mit fetchpriority="high" ziehst du ein kritisches Script vor, etwa den Code, der deine Seite interaktiv macht. Mit fetchpriority="low" stufst du weniger wichtige Scripts wie Analytics zurück, damit sie kritischen Ressourcen nicht die Bandbreite wegnehmen. Das Attribut wird von allen modernen Browsern unterstützt, ältere Browser ignorieren es einfach.

<!-- Kritisches Script bevorzugt laden -->
<script src="app.js" defer fetchpriority="high"></script>

<!-- Analytics zurückstufen -->
<script src="analytics.js" async fetchpriority="low"></script>

Beispiele

Externes Script mit defer

Script mit defer im head
<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
  <script src="app.js" defer></script>
</head>
<body>
  <h1>Meine App</h1>
  <button id="btn">Klick mich</button>
</body>
</html>
Vorschau

Das Script lädt parallel zum HTML-Parsing und startet erst, wenn das DOM fertig ist. Der Button ist garantiert da, wenn das Script läuft.

Inline-Script

Inline-Script am Ende des body
<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
</head>
<body>
  <h1>Inline-Script Demo</h1>
  <p id="output">Warte...</p>

  <script>
    document.getElementById("output").textContent = "JavaScript läuft!";
  </script>
</body>
</html>
Vorschau

Das Inline-Script steht am Ende des Body. Dadurch ist das DOM schon verfügbar und wir können direkt auf die Elemente zugreifen.

Module-Script

ES6-Modul mit type=module
<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
</head>
<body>
  <h1>ES6 Module</h1>

  <script type="module">
    import { greet } from "./utils.js";
    console.log(greet("Welt"));
  </script>
</body>
</html>
Vorschau

Mit type="module" kannst du moderne JavaScript-Features nutzen: Import/Export, strict mode by default, eigener Scope. Das Script verhält sich automatisch wie ein defer-Script.

Barrierefreiheit

JavaScript kann die Barrierefreiheit sowohl verbessern als auch verschlechtern. Hier sind die wichtigsten Punkte:

  • Progressive Enhancement: Baue deine Seite so, dass die Grundfunktionen auch ohne JavaScript funktionieren. Nicht alle Nutzer haben JavaScript aktiviert, und Screenreader verarbeiten JavaScript-generierte Inhalte manchmal verzögert. Die Basis-Inhalte sollten immer im HTML stehen.
  • Fokus-Management: Wenn JavaScript den DOM verändert, etwa ein Modal öffnet oder Inhalte nachladen, muss der Fokus aktiv auf das neue Element gesetzt werden. Sonst bleibt der Fokus an der alten Stelle und Tastaturnutzer verlieren die Orientierung. Nutze element.focus() nach DOM-Änderungen.
  • aria-live-Regionen: Dynamische Inhaltsänderungen (z.B. Statusmeldungen, Fehlermeldungen, Benachrichtigungen) werden von Screenreadern nicht automatisch vorgelesen. Verwende aria-live="polite" oder aria-live="assertive" auf dem Container, damit der Screenreader Änderungen ankündigt.
  • Event-Handler zugänglich gestalten: Verwende nicht nur onclick, sondern auch onkeydown oder onkeyup für Tastaturzugänglichkeit. Besser noch: Nutze semantische Elemente wie <button> und <a>, die Tastaturinteraktion automatisch unterstützen, statt Klick-Events auf <div>-Elemente zu setzen.
  • Script-Ladezeit und Accessibility: Wenn Scripts das Rendering blockieren, kann die Seite für Nutzer mit langsameren Geräten oder assistiven Technologien unbrauchbar werden. Verwende defer oder async, um das Laden der Seite nicht zu verzögern.

Häufige Fehler

Script im head ohne defer/async ist der Klassiker. Ohne diese Attribute blockiert das Script das Rendering komplett. Der Browser lädt das Script, führt es aus, und erst dann geht’s weiter mit dem HTML. Das Ergebnis: Deine Seite wirkt langsam, obwohl sie vielleicht nur 2 KB groß ist. Lösung: defer oder async verwenden, oder das Script ans Ende des Body verschieben.

type=“text/javascript” ist überflüssig. Früher war das mal notwendig, aber heute ist JavaScript der Standard. Browser gehen automatisch davon aus, dass Scripts JavaScript enthalten. Das type-Attribut brauchst du nur für type="module" oder spezielle Fälle wie JSON-LD für Structured Data.

Self-closing script tags funktionieren nicht. In HTML ist <script src="app.js" /> ungültig. Du brauchst immer ein schließendes </script>-Tag, auch wenn das Element leer ist. Der Browser interpretiert einen self-closing Tag als Beginn eines Elements, nicht als vollständiges Element. Das führt zu kaputtem HTML-Parsing und Scripts, die nicht laden.

Browser-Kompatibilität

Das script-Element wird seit den Anfängen von HTML von allen Browsern unterstützt. Auch die Attribute defer, async, type='module' und fetchpriority werden von allen modernen Browsern unterstützt.

ClientUnterstützungHinweise
ChromeKomplett
FirefoxKomplett
SafariKomplett
EdgeKomplett
OperaKomplett

Email-Kompatibilität

Scripts werden in E-Mails aus Sicherheitsgründen komplett entfernt. E-Mail-Clients strippen alle script-Tags und Event-Handler wie onclick. E-Mails müssen mit statischem HTML und CSS auskommen.

ClientUnterstützungHinweise
Apple MailKeineScripts werden aus Sicherheitsgründen entfernt.
GmailKeineGmail entfernt alle script-Tags vollständig.
OutlookKeineOutlook entfernt Scripts und Event-Handler komplett.
ThunderbirdKeineKeine Unterstützung für Scripts in E-Mails.
Yahoo MailKeineScripts werden aus Sicherheitsgründen entfernt.

Verwandte Elemente

Bleib auf dem Laufenden

Erhalte neue Inhalte direkt in dein Postfach

Mit der Anmeldung akzeptierst du unsere Datenschutzerklärung. Du kannst dich jederzeit über den Link in den E-Mails wieder abmelden.

Was erwartet dich?

Neue Artikel & Videos

Wenn ich was Neues veröffentliche, erfährst du's hier zuerst.

Plattform & Kurs-Updates

Neue Kurse, Referenz-Updates und gelegentlich Sonderpreise zum Launch.

Einmal die Woche in deinem Postfach

Kurz, auf den Punkt, kein Spam.