JavaScript/Anwendung und Praxis/JavaScript und CSS

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Inhaltsverzeichnis

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 Benutzereingabe gewisse Elemente ein- oder ausblenden. Es sind aber auch – mit entsprechendem Aufwand – visuelle Effekte und komplexe Animationen möglich.

JavaScript besitzt keine eigenen Techniken zur Gestaltung einer Webseite, sondern stellt lediglich eine Schnittstelle zur Formatierungssprache Cascading Stylesheets (CSS) bereit. 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.

Bevor Sie die verschiedenen Möglichkeiten kennenlernen, wie Sie CSS-Formatierungen durch JavaScript verändern können, sollten Sie sich die Konzepte des Unobtrusive JavaScript in Erinnerung rufen.

  • HTML ist für die Strukturierung der Inhalte zuständig. Idealerweise bleiben die HTML-Strukturen übersichtlich, IDs und Klassen sind sparsam gesetzt und aussagekräftig, sodass eindeutige Angriffspunkte für CSS-Regeln existieren.
  • Ausgelagerte Stylesheets sprechen gezielt Elemente im Dokument an und formatieren sie mit CSS-Eigenschaften.
  • Wenn nun die dritte Technik – JavaScript – hinzutritt, sollten Sie dieses Modell konsequent fortführen.
Empfehlung: Orientieren Sie sich an folgenden Faustregeln:
  • Definieren Sie die Formatierungsregeln im zentralen Stylesheet, nicht im JavaScript. Trennen sie CSS-Anweisungen vom JavaScript-Code.
  • Sorgen Sie im JavaScript dafür, dass diese Formatierungsregeln angewendet werden – beispielsweise indem Sie ein Element dynamisch einer Klasse hinzufügen. Durch diese Änderung der Klassenzugehörigkeit kann eine Regel im Stylesheet greifen, deren Selektor die soeben gesetzte Klasse enthält.
  • Sie können nicht nur ausgelagerte Stylesheet-Regeln auf ein Element anwenden, sondern auch direkt bestimmte CSS-Eigenschaften einzelner Elemente ä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 ergibt nur in Sonderfällen Sinn, deshalb sollten Sie sich zunächst mit der besagten Arbeitsweise vertraut machen.

[Bearbeiten] Stylesheet-Regeln auf ein Element anwenden

Eine sehr effektive und aus Programmierersicht relativ simple Vorgehensweise ist das Setzen bzw. Entfernen einer Klasse, der ein Element zugewiesen ist. Wenn man einem Element eine bestimmte Klasse zuweist, die in den Darstellungsregeln so verwendet wird, dass dieses Element anders als ohne diese Klasse aussieht, dann steuert man mit JavaScript indirekt, und damit der Trennung der Schichten von Markup, Layout und Behaviour folgend, das Aussehen dieses Elements - und seiner Nachfahren.

Der Clou dieser Vorgehensweise ist, dass Sie mit dem Setzen der Klasse an einem Element nur eine minimale Änderung am DOM vornehmen. Diese Änderung führt dazu, dass eine Regel aus dem Stylesheet plötzlich auf bestimmte Elemente greift – der Browser wendet daraufhin automatisch die definierten Formatierungen an.

[Bearbeiten] className und classList

Um nun einem Element eine Klasse zuzuweisen oder wieder zu entfernen gibt es - auch wieder aus historischen Gründen - zweierlei Möglichkeiten:

  1. className - einfach zu nutzen bei nur einer Klasse
  2. classList - bequem zu nutzen, vor allem bei mehrfacher Klassenzuweisung

Die Eigenschaft className entspricht in etwa dem class-Attribut im HTML Quelltext. Dieses Attribut kann durch Leerzeichen getrennt verschiedene Klassen enthalten. Vor der Einführung von classList, einem Objekt mit praktischen Methoden, war das Manipulieren der className-Eigenschaft genau dann mühsam, wenn man mit mehreren Klassen hantieren musste. Daher ist es nun sinnvoll, auf die Verwendung von className zugunsten von classList zu verzichten.

Beispiel: einfache Klassenzuweisung in JavaScript
// <body> die Klasse "js-enabled" geben
document.body.className = "js-enabled"; // entspricht <body class="js-enabled">
document.body.classList.add("js-enabled");
 
// <body> nun die Klasse "js-enabled" wieder wegnehmen:
document.body.className = ""; // entspricht <body class="">
document.body.classList.remove("js-enabled");
Das body-Element wird der Klasse js-enabled zugeordnet. Beispielhaft geschieht dies doppelt, sowohl mit className als auch mit classList. Die Methoden add und remove achten darauf, ob eine Klasse dieses Namens bereits vorhanden ist, oder nicht. Daher wird mit classList.add die Klasse js-enabled nicht doppelt vergeben.

Die Vorteile von classList werden ganz schnell deutlich, wenn mit mehreren Klassen hantiert werden muss:

Beispiel: mehrfache Klassenzuweisung in JavaScript
// <body> die Klassen "js-enabled" und "unconfirmed" geben
document.body.className = "js-enabled unconfirmed"; // entspricht <body class="js-enabled unconfirmed">
 
document.body.classList.add("js-enabled");
document.body.classList.add("unconfirmed");
 
// <body> nur die Klasse "unconfirmed" wieder wegnehmen:
document.body.className = document.body.className.replace(/\b?unconfirmed/, "");
document.body.classList.remove("unconfirmed");
Um mit className die Klasse unconfirmed zu entfernen, muss eine Stringoperation durchgeführt werden, welche hier mit der String-Methode replace unter Zuhilfenahme eines regulären Ausdrucks geschieht. Mit den Methoden von classList ist diese "Handarbeit" nicht mehr notwendig.

[Bearbeiten] Zusammenspiel von CSS-Regeln und Klassenzuweisung

Nehmen wir einmal an, wir wollten einen Lückentext gestalten, bei dem die Lücken auf Knopfdruck sichtbar werden sollen. Dazu bräuchten wir ein passendes Element (z.B. <span>), welches die Wörter enthält, die später zu Lücken werden sollen. Außerdem bräuchten wir eine Darstellungsregel, die den Inhalt unsichtbar macht, wohl aber die Lücken als solche kennzeichnet. Zuguterletzt bräuchte es eine Klasse, die dafür sorgt, dass die ausgeblendeten Wörter wieder dargestellt werden.

Betrachten wir zuerst den CSS-Teil:

Beispiel: Darstellungsregeln für Lückentext
span {
  visibility: hidden;
}
 
.spoil span {
  visibility: visible;
}
Die CSS-Eigenschaft visibility macht Inhalte in <span>-Elementen unsichtbar. Diese Unsichtbarkeit wird bei den <span>-Elementen wieder aufgehoben, die sich in einem Element befinden, welches entweder selbst die Klasse spoil hat, oder ein Nachfahre eines solchen Elements ist.

Der JavaScript-Teil tut im Wesentlichen nichts anderes, als <body> die Klasse spoil hinzu zu fügen, oder zu entfernen:

Beispiel: JavaScript für Lückentext
(function () {
  document.addEventListener("DOMContentLoaded", function () {
    var spoil = document.getElementById("spoil"),
      className = "spoil";
 
    if (spoil) {
      spoil.addEventListener("click", function () {
        document.body.classList.toggle(className);
      });
    }
  });
}());
Das Script selbst sitzt in einem sofort ausgeführten Funktionsausdruck, der selbst eine (anonyme) Funktion definiert, welche genau dann ausgeführt werden soll, wenn das HTML-Dokument vollständig geladen wurde. In dieser anonymen Funktion wird nach einem Element mit der ID spoil gesucht, einem <button> zum hin- und her schalten. Die Funktion, die beim Anklicken des Buttons aktiv wird, fügt abwechselnd die Klasse spoil dem <body> hinzu oder entfernt sie wieder, wofür classList die Methode toggle kennt.

Nun haben wir die wesentlichen Bausteine für den Lückentext zusammen. Mit CSS sorgen wir dafür, dass die Inhalte ausgeblendet und somit Lücken geschaffen werden. Mit JavaScript schalten wir zwischen Rätsel- und Lösungsansicht hin und her. Hier nun eine fertige Rätselseite:

Beispiel: Rätselseite mit Lückentext ansehen …
<button data-on="einblenden." data-off="ausblenden." id="spoil"></button>
button {
  display: block;
  margin: 0 auto;
}
 
button:after {
  content: attr(data-on);
}
 
.spoil button:after {
  content: attr(data-off);
}
Damit die Beschriftung des Klickbuttons sich passend mitändert, wurden die notwendigen Beschriftungen als data-Attribute notiert. In HTML5 können Sie jederzeit solche Attribute notieren, um sie z.B. im Kontext von generiertem Inhalt in CSS zu nutzen.

Über dieses Modell können Sie auch komplexere Aufgabenstellungen lösen, denn Ihnen stehen alle Möglichkeiten der CSS-Selektoren zur Verfügung. Beispielsweise können Sie mittels Nachfahrenselektoren Elemente formatieren, die unterhalb des mit der Klasse markierten Elements liegen. So können Sie durch die Änderung der Klasse gleich mehrere enthaltene, im DOM-Baum unterhalb liegende Elemente formatieren, ohne diese einzeln anzusprechen.

Beispiel: komplexere Darstellungswechsel mittels dynamisch vergebener Klassen ansehen …
<form>
  ...
  <p><button>Daten versenden</button></p>
  <p class="notice">...</p>
</form>
form {
  background: white;
  border: 1px solid #f00;
  border-radius: 0.5em;
  box-shadow: 0 0 10px #f00 inset;
  padding: 0.5em 1em;
}
 
form button {
  color: red;
  text-decoration: line-through;
}
 
form.percentage-100 button {
  color: inherit;
  text-decoration: inherit;
}
 
.percentage-20 {
	border-color: #f60;
	box-shadow: 0 0 10px #f60 inset;
}
 
.percentage-100 {
	border-color: #0f0;
	box-shadow: 0 0 10px #0f0 inset;
}
 
.notice {
	border-color: #f00;
	border-radius: 0.5em;
	box-shadow: 0 0 20px #f00 inset;
	padding: 1em 2em;
}
 
.percentage-20 .notice {
	border-color: #f60;
	box-shadow: 0 0 20px #f60 inset;
	padding: 1em 2em;
}
 
.percentage-100 .notice {
	border-color: #0f0;
	box-shadow: 0 0 20px #0f0 inset;
	padding: 1em 2em;
}
Das Beispiel zeigt verschiedene Klassen, die verschiedene Prozentstufen repräsentieren (hier nur eine Auswahl aus .percentage-10 bis .percentage-100). Die Darstellungsregeln für das Formular und den .notice-Textabsatz gehen von einer Prozentstufe null aus, die grundsätzlich angewendet werden. Wenn nun JavaScript bei der Prüfung feststellt, dass mehr als 0% der Angaben gemacht wurden, weist es dynamisch dem form-Element die passende Klasse zu, was sich unmittelbar auf die Farbgebung sowohl des Formulars selbst, als auch dem darin enthaltenen .notice-Textabsatzes, auswirkt, da diese Klassen Teile der bisher gültigen Darstellungsregeln modifizieren.

[Bearbeiten] Direktformatierung über das style-Objekt

[Bearbeiten] Inline-Styles in HTML

Um direkt einzelne HTML-Elemente mit CSS zu formatieren, existiert das style-Attribut, welches eine Liste von Eigenschafts-Wert-Zuweisungen enthält.

Ein HTML-Beispiel:

Beispiel
<p style="color: red; background-color: yellow; font-weight: bold;">Fehler!</p>
Beachten Sie: Gegenüber dem Einsatz von zentralen Formaten in Stylesheets sind diese sogenannten 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.

[Bearbeiten] Das style-Objekt als Schnittstelle zu Inline-Styles

JavaScript 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 les- und schreibbare Objekteigenschaft. Zu der CSS-Eigenschaft color existiert also eine Objekteigenschaft element.style.color vom Type String.

Folgendes Beispiel veranschaulicht das Setzen der Hintergrundfarbe eines Elements auf rot:

Beispiel
document.getElementById('beispielID').style.backgroundColor = 'red';

Als Werte müssen Sie stets Strings angeben genau in der Form, wie sie in CSS spezifiziert sind. Das gilt auch für Zahlenwerte, die eine Einheit erfordern:

Beispiel
element.style.marginTop = 15; // Falsch!
element.style.marginTop = '15px'; // Richtig
Beachten Sie: CamelCase statt Bindestriche!
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 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.
Beachten Sie: Abweichungen vom besagten Schema:
Wenn Sie die CSS-Eigenschaft float mit JavaScript ändern wolllen, müssen Sie den Begriff cssFloat verwenden, da float ein Reserviertes Wort ist. Der Internet Explorer verwendete in älteren Versionen (bis IE8) den Begriff styleFloat.

[Bearbeiten] Sinnvoller Einsatz des style-Objektes

Das Setzen von CSS-Formatierungen direkt über das style-Objekt ist zwar einfach. Doch sollten Sie diese Präsentationsregeln wie gesagt nicht im JavaScript, sondern sie z.B. in einer Klasse im Stylesheet unterbringen. Nur in manchen Fällen ist die Verwendung von Inline-Styles notwendig: Wenn der Eigenschaftswert nicht fest steht, sondern erst im JavaScript berechnet wird. Das ist der Fall z.B. bei Animationen oder bei einer Positionierung abhängig von der Mauszeiger-Position wie beim Drag and Drop.

[Bearbeiten] style ist nicht zum Auslesen der gegenwärtigen Eigenschaftswerte geeignet

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 besagten Objekteigenschaften (.style.cssEigenschaft) sind allesamt leer, wenn sie nicht im betreffenden HTML-Element über ein style-Attribut oder wie beschrieben mit JavaScript gesetzt wurden. Folgendes Beispiel verdeutlicht dies:

Beispiel
<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
);

[Bearbeiten] CSS-Eigenschaften auslesen

Über das style-Objekt besteht wie gesagt kein Zugriff auf den aktuellen CSS-Eigenschaftswert eines Elements, sofern kein entsprechender Inline-Style gesetzt wurde. Dies ist meistens der Fall, denn die Formatierungen gehen üblicherweise auf zentrale Formatierungen in ausgelagerten Stylesheets und auf die Standardformatierungen des Browsers zurück.

Das Auslesen des gegenwärtigen Werts von CSS-Eigenschaften eines Elements gestaltet sich als schwierig. 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, wie sie in der CSS-Fachsprache genannt werden.

Der W3C-Standard, der die Schnittstelle zwischen JavaScript und CSS und damit der Darstellung eines Dokuments festlegt, kennt zu diesem Zweck die Methode window.getComputedStyle(). Sie erwartet ein Elementobjekt als ersten Parameter und einen String mit einem CSS-Pseudo-Element als zweiten Parameter (beispielsweise "after", "before", "first-line" oder "first-letter"). Wenn man nicht die Formatierung des Pseudo-Elements abfragen will, übergibt man schlichtweg null als zweiten Parameter.

getComputedStyle gibt ein Objekt zurück, das genauso aufgebaut ist wie das bereits besprochene element.style-Objekt. Es enthält für jede CSS-Eigenschaft eine entsprechende Objekteigenschaft mit dem aktuellen berechneten Wert.

Beispiel
var element = document.getElementById('beispielID');
var computedStyle = window.getComputedStyle(element, null);
window.alert('Textfarbe: ' + computedStyle.color);
window.alert('Elementbreite: ' + computedStyle.width);

Die berechneten Werte (computed values), die getComputedStyle zurückgibt, sind nicht in jedem Fall identisch mit den Werten, die Sie im Stylesheet notiert haben. Der Längenwert in margin-top: 2em; und der Prozentwert in font-size: 120%; werden von den verbreiteten grafischen Browsern letztlich 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 Farbwerte 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 alternativen Schreibweise.


[Bearbeiten] Elementbox-Größen auslesen über Microsoft-Eigenschaften

Über die vorgestellten Techniken ist es nicht browserübergreifend möglich, die aktuelle Höhe und Breite einer Element-Box in der Einheit Pixel auszulesen. Stattdessen sollten Sie folgende Eigenschaften der Elementobjekte verwenden. Sie wurden ursprünglich von Microsoft erfunden, erfreuen sich aber breiter Browser-Unterstützung. Im Gegensatz zu getComputedStyle geben sie keine String-Werte samt Einheiten zurück, sondern direkt JavaScript-Zahlen (Number-Werte) in der Einheit Pixel.

  • offsetWidth und offsetHeight: liefern die Breite bzw. Höhe der Rahmen-Box des Elements. Das bedeutet, dass der Innenabstand (padding) und der Rahmen (border) inbegriffen sind, der Außenrahmen hingegen (margin) nicht.
  • clientWidth und clientHeight: liefern Breite bzw. Höhe der Innenabstand-Box des Elements. Das bedeutet, dass 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: geben die tatsächlich angezeigte Breite bzw. Höhe des Inhalts wieder. Wenn das Element kleiner ist, als der Inhalt es erfordert, also Bildlaufleisten angezeigt werden, so geben diese Eigenschaften die Größe des des aktuell sichtbaren Ausschnittes wieder.

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:

Beispiel
var element = document.getElementById('beispielID');
window.alert('Breite: ' + element.offsetWidth + '\nHöhe: ' + element.offsetHeight);

Falls sie die innere Größe benötigen, so können Sie zunächst die aktuellen Werte der jeweiligen padding-Eigenschaften auslesen. Das sind padding-left und padding-right für die Breite bzw. padding-top und padding-bottom für die Höhe. Diese substrahieren sie von offsetWidth bzw. offsetHeight, um die tatsächliche Innengröße zu erhalten.

[Bearbeiten] Siehe auch

[Bearbeiten] Quellen

Information

Bei diesem Text handelt es sich um eine überarbeitete Übernahme aus der Einführung in JavaScript von Mathias Schäfer.[1]
  1. Mathias Schäfer: Organisation von JavaScripten: Module und Kapselung
Meine Werkzeuge
Namensräume

Varianten
Aktionen
Übersicht
Index
Mitmachen
Werkzeuge
Spenden
SELFHTML