Mit JavaScript können Sie die Darstellung des Dokuments dynamisch ändern, während es im Browser angezeigt wird. Dies ist ein wesentlicher Bestandteil der Interaktivität, die Sie einem Dokument mittels Javascript hinzufügen können. Die Möglichkeiten sind vielfältig: Beispielsweise können Sie als Reaktion auf eine Eingabe gewisse Elemente ein- und ausblenden. Es sind aber auch – mit entsprechendem Aufwand – visuelle Effekte und komplexe Animationen möglich.
Die Programmiersprache JavaScript besitzt keine eigenen Techniken, um die Gestaltung einer Webseite zu beeinflussen. Vielmehr besitzt JavaScript eine Schnittstelle zur Formatierungssprache Cascading Stylesheets (CSS). Mittels JavaScript können Sie also sämtliche Formatierungen vornehmen, die CSS möglich macht. Daher sollten Sie die Grundlagen von CSS bereits beherrschen, bevor Sie Dokumente mittels JavaScript umformatieren.
Das dynamische Ändern der Darstellung bildet einen großen Komplex in der JavaScript-Programmierung - ein anderer ist das dynamische Ändern der Inhalte über das Document Object Model (DOM). Über das DOM können Sie Elemente hinzufügen oder löschen, Attributwerte setzen und Textinhalte einfügen oder verändern. In der Praxis gehen diese beiden Aufgaben - den Inhalt und dessen Darstellung modifizieren - oft miteinander einher.
Bevor Sie die verschiedenen Möglichkeiten kennenlernen, wie Sie ein Element CSS-Formatierungen mithilfe von JavaScript verändern können, sollten Sie sich die Konzepte des Unobtrusive JavaScript in Erinnerung rufen.
Wenn Sie bereits einige Layouts mit CSS umgesetzt haben, sollten Sie die Aufgaben der Webtechniken kennen und deren sinnvolle Anwendung bereits beherrschen:
Diese Arbeitsweise hat enorme Vorteile bei der Webseiten-Entwicklung. Inhalt und Präsentation können unabhängig voneinander geändert werden. Mit wenig Aufwand kann die gewünschte Präsentation erzielt werden.
Wenn nun die JavaScript hinzutritt, sollten Sie dieses Modell konsequent fortführen. Orientieren Sie sich an folgenden Faustregeln:
Sie können nicht nur ausgelagerte CSS-Regeln auf ein Element anwenden, sondern auch direkt CSS-Eigenschaften von einzelnen Elementen ändern. Dies entspricht dem style
-Attribut in HTML. Diese Vermischung von HTML und CSS bzw. JavaScript und CSS sollten Sie möglichst vermeiden. Diese Direktformatierung ist nur in Sonderfällen sinnvoll und nötig.
Eine einfache Methode, um die Darstellung von Elementen per JavaScript zu ändern, ist das Hinzufügen einer Klasse. Die Formatierungen für diese Klasse wird im Stylesheet untergebracht. Damit wird der empfohlenen Trennung vom JavaScript-Code Genüge getan.
Betrachten wir als Beispiel ein JavaScript, dass die Eingaben eines Formulars überprüft. Beim Absenden des Formulars wird eine Handler-Funktion für das Ereignis submit
aktiv. Diese Funktion soll fehlerhafte Formularfelder rot markieren.
Nehmen wir an, die input
-Eingabefelder sind standardmäßig im Stylesheet so formatiert:
input { padding: 4px 6px; border: 1px solid #555; background-color: #fafafa; }
Im Stylesheet wird nun eine Regel definiert mit den Eigenschaften für fehlerhafte Felder. Wir nutzen dazu einen Selektor mit dem Elementnamen input
kombiniert mit der Klasse fehlerhaft
:
input.fehlerhaft { border-color: red; background-color: #fff8f5; }
Am Anfang trifft der Selektor input.fehlerhaft
auf kein Feld im Dokument zu. Um ein Eingabefeld umzuformatieren und die Regel anzuwenden, vergeben wir diese Klasse an das gewünschte input
-Element.
Die Klassen eines Elements sind in JavaScript über die Eigenschaft classList
des entsprechenden Elementobjekts zugänglich. classList
ist listenartiges Objekt, das alle Klassen beinhaltet. Das Objekt bietet verschiedene Methoden an, um die Klassen eines Elements abzufragen und zu ändern.
Das Schema zum Hinzufügen einer Klasse lautet:
element.classList.add('klassenname');
Die beispielhafte Formularüberprüfung sieht so aus: Wir definieren eine Funktion formularÜberprüfung
, die als Handler für das Ereignis submit
registriert wird (siehe Ereignis-Verarbeitung). Die Funktion sucht das Formularfeld mittels document.getElementById(…)
heraus. Ist der Wert des Feldes leer, wird eine Meldung ausgegeben und das Feld bekommt die Klasse fehlerhaft
.
function formularÜberprüfung(event) { // Suche das Formularfeld heraus und // speichere es in eine Variable: var element = document.getElementById('kontaktformular-name'); // Prüfe den Wert des Feldes: if (element.value === '') { // Zeige im Fehlerfall ein Hinweisfenster: window.alert('Bitte geben Sie Ihren Namen an.'); // Weise dem Element die Klasse »fehlerhaft« zu: element.classList.add('fehlerhaft'); // Setze den Fokus auf das Feld: element.focus(); // Verhindere das Absenden des Formulars // (unterdrücke die Standardaktion des Ereignisses): event.preventDefault(); } } // Überwache das submit-Ereignis beim Formular document.getElementById('kontaktformular') .addEventListener('submit', formularÜberprüfung, false);
Der zugehörige HTML mit den nötigen IDs könnte so aussehen:
<form action="…" method="post" id="kontaktformular"> <p> <label> Ihr Name: <input type="text" name="name" id="kontaktformular-name"> </label> </p> … weitere Felder … <p><button>Absenden</button></p> </form>
Das Hinzufügen der Klasse an einem Element ist nur eine minimale JavaScript-Änderung. Sie führt dazu, dass eine Regel aus dem Stylesheet auf bestimmte Elemente greift. Der Browser wendet daraufhin die definierten Formatierungen an.
Damit können Sie auch komplexere Aufgabenstellungen lösen, denn Ihnen stehen alle Möglichkeiten von CSS-Selektoren zu Verfügung. Beispielsweise können Sie mittels Nachfahrenselektoren Elemente formatieren, die unterhalb des mit der Klasse markierten Elements liegen. So können Sie durch das Ändern einer Klasse gleich mehrere, im DOM-Baum unterhalb liegende Elemente formatieren, ohne diese einzeln anzusprechen.
TODO: Beispiel dazu. Mit Nachfahrenselektoren größere Umformatierungen vornehmen, ohne alle Elemente einzeln anzusprechen
Das classList
-Objekt erlaubt es nicht nur, eine Klasse hinzuzufügen, sondern auch sie zu löschen, zu ersetzen und ihr Vorhandensein abzufragen. Hier eine kleine Übersicht:
element.classList.add('klasse')
fügt eine Klasse hinzu.element.classList.remove('klasse')
löscht eine Klasse.element.classList.toggle('klasse')
fügt eine Klasse hinzu, falls sie noch nicht vorhanden ist, oder löscht sie, falls sie schon vorhanden ist.element.classList.contains('klasse')
gibt zurück, ob eine Klasse vorhanden ist. Die Funktion gibt einen Boolean-Wert zurück.element.classList.replace('klasse1', 'klasse2')
ersetzt eine Klasse mit einer anderen, sofern sie vorhanden ist.style
-ObjektZur direkten CSS-Formatierung eines HTML-Elements existiert das style
-Attribut. Es ist eine Zuordnungsliste mit Eigenschaft-Wert-Paaren. Ein HTML-Beispiel:
<p style="color: red; background-color: yellow; font-weight: bold;">Fehler!</p>
Gegenüber dem Einsatz eines Stylesheets sind diese Inline-Styles (eingebettete Formatierungen) ineffektiv und führen zu zu einer Vermischung von HTML und CSS, die die Wartbarkeit des Dokuments verschlechtert. Sie sollten Sie daher nur in Ausnahmefällen einsetzen, auf die wir später noch zu sprechen kommen.
style
-Objekt als Schnittstelle zu Inline-StylesJavaScript bietet eine Schnittstelle zu diesem style
-Attribut: Das style
-Objekt bei jedem Elementobjekt. Das style
-Objekt hat für jede mögliche CSS-Eigenschaft eine entsprechende Objekteigenschaft. Der CSS-Eigenschaft color
entspricht also eine Objekteigenschaft element.style.color
vom Typ String.
CSS-Eigenschaftsnamen mit Bindestrichen, wie z.B. background-color
, können nicht unverändert als JavaScript-Eigenschaftsnamen übernommen werden. Deshalb werden sie im sogenannten Camel-Case (Groß- und Kleinschreibung im Kamel-Stil) notiert: Der Bindestrich fällt weg, dafür wird der darauf folgende Buchstabe zu einem Großbuchstaben. Aus background-color
wird also backgroundColor
, aus border-left-width
wird borderLeftWidth
und so weiter. Die Großbuchstaben in der Wortmitte werden mit Höcker eines Kamels verglichen.
Folgendes Beispiel veranschaulicht das Setzen der Hintergrundfarbe eines Elements auf rot:
document.getElementById('beispielID').style.backgroundColor = 'red';
Als Werte müssen Sie stets Strings angeben. Darin muss ein gültiger Eigenschaftswert stehen. Das gilt auch für Zahlenwerte, die eine Einheit erfordern:
element.style.marginTop = 15; // Falsch! element.style.marginTop = '15px'; // Richtig
Es gibt einen Sonderfall bei der Übersetzung von CSS-Eigenschaftsnamen in JavaScript-Eigenschaftsnamen. Das betrifft die CSS-Eigenschaft float
. Dieser Name war einmal ein reserviertes Wort in JavaScript, d.h. er konnte nicht als Bezeichner verwendet werden.
Auch wenn das mittlerweile kein Problem mehr ist, sollten Sie statt float
die JavaScript-Eigenschaft cssFloat
notieren, also z.B. element.style.cssFloat
.
style
-ObjektsDas Setzen von CSS-Formatierungen direkt über das style
-Objekt ist zwar einfach. Doch Sie sollten diese Präsentationsinformationen wie gesagt nicht im JavaScript, sondern in einer Regel im Stylesheet unterbringen. Die Verwendung von Inline-Styles ist nur dann notwendig, wenn der Eigenschaftswert nicht fest steht, sondern im JavaScript berechnet wird. Das ist der Fall z.B. bei Animationen oder bei einer Positionierung abhängig von der Mauszeiger-Position wie.
Das style
-Objekt wird immer wieder missverstanden. Sie können über das style
-Objekt nicht den aktuellen, berechneten Wert einer CSS-Eigenschaft auslesen. Sie können damit lediglich Inline-Styles setzen und die bereits gesetzten auslesen.
Die Objekteigenschaften (element.style.eigenschaft
) sind allesamt leer, wenn sie per HTML-Inline-Style (style
-Attribut) oder wie beschrieben mit JavaScript gesetzt wurden. Folgendes Beispiel verdeutlicht dies:
<p id="ohne-inline-styles">Element ohne Inline-Styles</p> <p id="mit-inline-styles" style="color: red">Element mit Inline-Styles</p>
// Gibt einen leeren String aus: window.alert( document.getElementById('ohne-inline-styles').style.backgroundColor ); // Gibt »red« aus, weil Inline-Style gesetzt wurde: window.alert( document.getElementById('mit-inline-styles').style.backgroundColor );
Wenn man in Erfahrung bringen will, welche tatsächliche Textfarbe oder welche Pixel-Breite ein Element hat, dann ist nach den sogenannten berechneten Werten (englisch computed values) gefragt.
getComputedStyle
Der Standard, der die Schnittstelle zwischen JavaScript und CSS festlegt, definiert die globale Funktion window.getComputedStyle()
. Sie erwartet ein Elementobjekt als ersten Parameter und einen String mit einem CSS-Pseudo-Element als zweiten Parameter (beispielsweise '::after'
oder '::before'
). Sofern Sie nicht die Formatierung des Pseudo-Elements abfragen wollen, lassen Sie den zweiten Parameter einfach weg.
getComputedStyle()
gibt ein Objekt zurück, das genauso aufgebaut ist wie das bereits besprochene style
-Objekt. Es enthält für jede CSS-Eigenschaft eine entsprechende Objekteigenschaft mit dem aktuellen berechneten Wert.
var element = document.getElementById('beispielID'); var computedStyle = window.getComputedStyle(element); window.alert('Textfarbe: ' + computedStyle.color); window.alert('Elementbreite: ' + computedStyle.width);
Die berechneten Werte (computed values) sind nicht identisch mit den Werten, die Sie im Stylesheet notiert haben. Die Werte in margin-top: 2em;
und font-size: 120%;
werden in Pixelwerte umgerechnet, sodass getComputedStyle()
Werte mit der Einheit px
zurückgibt.
Auch beispielsweise bei Farbwerten können Sie nicht erwarten, dass das Format des berechneten Wertes mit dem des Stylesheets übereinstimmt. Denn es gibt in CSS verschiedene Formate, um Farben zu notieren. Notieren Sie im Stylesheet beispielsweise color: red
, so kann es sein, dass getComputedStyle()
für color
den Wert 'rgb(255, 0, 0)'
liefert. Dies ist derselbe Wert in einer anderen Schreibweise.
Sie können getComputedStyle()
nutzen, um die aktuelle berechnete Höhe (width
) und Breite <(height
) einer Element-Box auszulesen. Die Methode gibt dann einen String-Wert wie '560px'
zurück. Beim Standard-Box-Modell beziehen sich die CSS-Eigenschaft width
und height
auf die Innengröße. Das heißt Innenabstand (padding
), Rahmen (border
) und gegebenenfalls Außenrahmen (margin
) müssen hinzugefügt werden, um die vollständige Höhe und Breite des Elements zu berechnen.
Es gibt eine Reihe vom Eigenschaften der Elementobjekte, die diese Berechnungen vereinfachen. Im Gegensatz zu getComputedStyle()
geben sie keine String-Werte samt Einheiten zurück, sondern direkt JavaScript-Ganzzahlen (Number-Werte) in der Einheit Pixel.
offsetWidth
und offsetHeight
padding
) und der Rahmen (border
) inbegriffen sind, der Außenrahmen hingegen (margin
) nicht.clientWidth
und clientHeight
padding
inbegriffen ist, während border
und margin
nicht eingerechnet werden. Ebenso wird die Größe einer möglicherweise angezeigte Bildlaufleiste (Scrollbar) nicht einberechnet.scrollWidth
und scrollHeight
In den meisten Fällen werden Sie die äußere Größe eines Elements benötigen, also offsetWidth
und offsetHeight
. Das folgende Beispiel gibt die Größe eines Elements aus:
var element = document.getElementById('beispielID'); window.alert('Breite: ' + element.offsetWidth + ' Höhe: ' + element.offsetHeight);
…
…
…