05.06.05 // Der Div-Wahnsinn

Immer mehr Webdokumente scheinen aus nichts anderem als einer Ansammlung von div-Elementen zu bestehen. In den meisten Fällen könnte eine bessere Nutzung von CSS-Selektoren diese Masse von div-Elementen verhindern.

Original-Autor: Gez Lemon: Div Mania
Übersetzung: Eric Eggert

Zusammenfassung

Immer mehr Webdokumente scheinen aus nichts anderem als einer Ansammlung von div-Elementen zu bestehen. In den meisten Fällen könnte eine bessere Nutzung von CSS-Selektoren diese Masse von div-Elementen verhindern.

Original-Autor: Gez Lemon: Div Mania
Übersetzung: Eric Eggert

Inhalt

Was bedeutet Div-Wahnsinn?

Die div- und span-Elemente wurden in HTML 4 eingeführt um allgemeine Mechanismen zur Gruppierung von Elementen zur Verfügung zu stellen und um die Dokumente zu strukturieren. Das div-Element ist ein Block-Container, span ein Inlineelement.

Meist werden diesen Elementen id- und/oder class-Attribute hinzugefügt, damit sie mit CSS oder Scripting angesprochen werden können.

Der Div-Wahnsinn beginnt dort, wo Entwickler tabellenbasierte Layouts durch CSS-Layouts ersetzt haben jedoch das div-Element in solch einem Ausmaß missbrauchen, so dass sie mehr oder minder eine eigene Auszeichnungssprache erstellt haben, die fast ausschließlich aus verschachtelten div-Elementen besteht.

Das div-Element ist semantisch neutral: es hat keine Bedeutung außer der, dass es ein Containerelement ist. Es sollte nur benutzt werden, wenn es kein anderes Element mit einer Bedeutung gibt, das als Container dienen kann, wie Überschriften, Absätze, Listen, usw.

Ein typisches Dokument, das im Div-Wahn erstellt wurde, könnte so aussehen:

  1. <div id="wrapper">
  2. <div id="container">
  3. <div id="navigation">
  4. <div id="navhead">
  5. ...
  6. </div>
  7. <div id="navcontent">
  8. ...
  9. </div>
  10. </div>
  11. <div id="content">
  12. <div class="panel">
  13. ...
  14. </div>
  15. <div class="panel">
  16. ...
  17. </div>
  18. </div>
  19. </div>
  20. </div>

Entwickler, die in die div-Falle treten sind sich dessen meist noch nicht einmal bewusst. Wenn sie ein Dokument voller divs durch einen automatischen Auszeichnungsvalidator schicken, und sich dadurch von der strukturellen Richtigkeit des Dokumentes überzeugen, wird der Validator korrektes (X)HTML bestätigen; Er ist nicht in der Lage herauszufinden, ob die passendsten Elemente verwendet werden.

Viele Faktoren tragen zu diesem Problem bei, wie fehlendes Verständnis von Auszeichnungselementen (beachte missbiligte Elemente), vom CSS-Box-Modell, Vererbung und Kaskade und von der Wahl der richtigen Selektoren.

Im Gespräch mit Entwicklern, die ein gewisses Verständnis von CSS haben, zeigt sich, dass die größten Lücken im Bereich der Selektoren zu finden sind. Der Rest dieses Dokumentes gibt deshalb einen Überblick über die CSS 2.1-Selektoren.

Nach oben

Regel-Sets

Eine CSS-Datei besteht aus einer Sammlung von Regeln, wobei eine Regel aus einem Selektor und einem Deklarationsblock besteht. Da es meist mehr als eine Regel in einer Datei gibt wird diese auch als Regel-Set bezeichnet.

Der Selektor wählt diejenigen Elemente im Dokumentbaum, für die die Regel gilt. Falls der Selektor fehlerhaft ist ignorieren Browser alles innerhalb des Deklarationsblocks.

Der Deklarationsblock ist eine durch Semikolon (;) getrennte Liste von Null oder mehr Deklarationen, die von geschweiften Klammern ({ bzw. }) umgeben ist.

Eine einzelne Deklaration kann entweder leer sein oder ein Paar aus Eigenschaft und Wert, die von einem Doppelpunkt getrennt sind.

Betrachten wir folgendes Beispiel:

  1. h1
  2. {
  3. padding-top: 1em;
  4. border-bottom: 1px solid #ccc;
  5. }

In der obigen Regel ist der Selektor h1 und der Deklarationsblock alles in den geschweiften Klammern sowie die Klammern selbst. Der Deklarationsblock besteht aus zwei Deklarationen, die mit Semikolon getrennt sind. Da diese nur zum Trennen genutzt werden ist die Angabe bei der zweiten Deklaration nicht nötig aber legal. Dem ersten Merkmal, padding-top, wird der Wert 1em zugewiesen. Hierzu ist auch Anhang F er Spezifikation für eine Liste aller Eigenschaften zu beachten.

Nach oben

Spezifität

Um zu verstehen, wie Selektoren auf Elemente angewandt werden ist ein grundlegendes Verständnis von Vererbung und Kaskade nötig. Vererbung bedeutet, dass ein Element Eigenschaften von seinem Übergeordneten Element übernimmt. Wenn man beispielsweise eine Schriftgröße für die Navigation festlegt, so wird jedes untergeordnete Element diese Schriftgröße übernehmen, zum Beispiel Absätze oder Listenpunkte.
Nicht alle Eigenschaften werden vererbt, aber die meisten. Falls keine Vererbung einer Eigenschaft statt findet kann sie durch den Wert inherit erzwungen werden.

Kaskade hingegen beschreibt mehrere Regeln für ein Element. Spezifität wird benutzt um festzustellen, welche dieser Regeln anzuwenden ist. Beachte die Reihenfolge: Wenn zwei Selektoren die selbe Spezifität haben gilt der zuletzt definierte.

Nach oben

CSS-Selektoren

Selektoren sind Schemata, die feststellen, auf welche Elemente des Dokumentenbaumes die Stilregeln angewandt werden.

Im Beispiel oben ist das h1-Element das Selektorschema.
Es können auch kompexere Schemata angewandt werde, die spezifischer Elemente aus dem Dokumentenbaum auswählen können.

Der Universalselektor

Der Universalselektor wird durch ein Sternchen (*) ausgedrückt und steht für alle Elemente im Dokumentenbaum. Das folgende Beispiel würde allen Elementen eine hellgelbe Hintergrundfarbe zuweisen, die die background-color-Eigenschaft erhalten können, es sei denn ein spezifischerer Selektor würde benutzt.

Für alle anderen Definitionen werde ich die Spezifität nicht mehr erwähnen, aber es ist wichtig, das man im Hinterkopf behält, dass alle folgenden Beispiele nur dann angewandt werden, wenn keine spezifischeren Selektoren definiert werden.

  1. *
  2. {
  3. background-color: #ffc;
  4. }

Folgendes Beispiel würde auf alle Elemente die den Klassennamen attention haben angewandt.

  1. *.attention
  2. {
  3. background-color: #ffc;
  4. }

Wenn der Stern – wie im obigen Beispiel – am Schema beteilig ist kann er sicher weggelassen werden. Ein Schema .attention sollte so effektiv sein wie *.attention.

Nach oben

Der Typselektor

Der Typselektor entspricht jedem Vorkommen eines bestimmten Elementes im Dokumentenbaum. Das folgende Beispiel wählt alle p-Elemente aus und weist ihnen einen hellgelben Hintergrund zu:

  1. p
  2. {
  3. background-color: #ffc;
  4. }

Nach oben

Gruppieren von Selektoren

Wenn mehrere Selektoren den selben Deklarationsblock teilen können sie zusammengefasst werden indem sie durch Kommata abgetrennt werden. Folgendes Beispiel weist sowohl allen strong- als auch allen em-Elementen eine hellgelbe Hintergrundfarbe zu:

  1. strong, em
  2. {
  3. background-color: #ffc;
  4. }

Nach oben

Der Klassenselektor

Der Klassenselektor kann als alternative zu Attributselektoren benutzt werden. Er wird durch einen vorangestellten Punkt (.) gekennzeichnet und auf alle Elemente angewandt, die diese Klasse (class-Attribut) besitzen.

Folgendes Beispiel weist allen Listenpunkten mit der Klasse .attention zu:

  1. li.attention
  2. {
  3. background-color: #ffc;
  4. }

Wenn die Klasse auf mehrere Elemente angewandt werden soll können die Selektoren gruppiert werden oder der Universalselektor benutzt werden (*.className oder .className)

Nach oben

Der ID-Selektor

Innerhalb eines Webdokumentes muss das id-Attribut einzigartig sein, das heißt man kann nur ein bestimmtes Element des Dokumentenbaumes auswählen. Dem ID-Selektor wird ein Raute-Symbol (#) vorangestellt.

Folgendes Beispiel würde der Überschrift zweiter Ordnung mit der einzigartigen ID offers einen hellgelben Hintergrund zuweisen:

  1. h2#offers
  2. {
  3. background-color: #ffc;
  4. }

Da die ID einzigartig sein muss, macht es keine Probleme den Universalselektor mit dem ID-Selektor zu kombinieren (*#idName oder #idName). Zwecks Lesbarkeit und Instandhaltung ist es aber eine gute Idee den Elementnamen beizubehalten.

Nach oben

Abhängige Selektoren

Der Dokumentenbaum ist so aufgebaut, dass jedes Element im Baum ein übergeordnetes Element (Elternelement) hat, vom Wurzelelement abgesehen. Abhängige Selektoren werden benutzt um bestimmte Elemente, die in bestimmten Elternelementen vorhanden sind auszuwählen.

Abhängige Selektoren werden durch ein Leerzeichen zwischen zwei Selektoren gekennzeichnet, wobei der jeweils folgende Selektor im vorherigen enthalten sein muss. Folgendes Beispiel wählt alle strong-Elemente in einem Absatz aus und ordnet ihnen eine hellgelbe Hintergrundfarbe zu:

  1. p strong
  2. {
  3. background-color: #ffc;
  4. }

Nach oben

Der Kindselektor

Ein Kindselektor wird benutzt um ein untergeordnetes Element auszuwählen. Zwischen zwei Selektoren wird ein Größerzeichen notiert (>), mit dem Elternelement links und dem Kindelement rechts.

Im folgenden Beispiel wird der Hintergrund aller strong-Elemente hellgelb gefärbt, sofern sie Kindelemente von p sind.

  1. p>strong
  2. {
  3. background-color: #ffc;
  4. }

Der Unterschied zwischen Kindselektor und abhängigem Selektor ist, dass der abhängige Selektor strong auswählt woimmer es in p vorkommt, wogegen der Kindselektor spezifischer ist und nur elemente auswählt, die direkte Kindelemente von p sind. Beispiel:

  1. <p>
  2. Jon said,
  3. <q>
  4. That'll be good when it's <strong>finished</strong>.
  5. </q>
  6. If only he <strong>knew</strong>!
  7. </p>

Der abhängige Selektor würde beide strong-Elemente auswählen, der Kindselektor würde nur das letzte strong auswählen, da das erste kein Kindelement von p sondern von q ist.

Unglücklicherweise funktionieren Kindselektoren nicht im Internet Explorer 6.

Nach oben

Der Benachbarte- Geschwister- Selektor

Geschwisterelemente sind Elemente, die das selbe Elternelement haben. Benachbarte Geschwister sind Geschwisterelemente, die direkt aufeinander folgen. Sie werden durch ein Pluszeichen (+) zwischen den Selektoren gekennzeichnet. Folgendes Beispiel weist jedem h2-Element, das auf ein h1-Element folgt eine hallgelbe Hintergrundfarbe zu, falls sie das selbe Elternelement haben.

  1. h1+h2
  2. {
  3. background-color: #ffc;
  4. }

Nach oben

Attributselektoren

Attributselektoren wählen Elemente aus, die im Dokument Attribute besitzen. Attributselektoren funktionieren nicht im Internet-Explorer 6. In CSS 2.1 gibt es folgende vier Attributselektoren:

[Attr]

Der einfache Attributselektor wählt alle Elemente, die über das Attribut verfügen, der Wert des Attributes ist dabei egal. Nachstehendes Beispiel wählt alle a-Elemente aus, die über ein title-Attribut verfügen.

  1. a[title]
  2. {
  3. background-color: #ffc;
  4. }

Nach oben

[Attr=Wert]

Dieser Attributselektor findet alle Elemente, die über das angegebene Attribut verfügen und deren Wert mit dem angegebenen übereinstimmt. Folgendes Beispiel würde a-Elementen einen hellgelben Hintergrund zuweisen, falls diese über ein rel-Attribut mit dem Wert external verfügt.

  1. a[rel=external]
  2. {
  3. background-color: #ffc;
  4. }

Nach oben

[Attr~=Wert]

Einige Attribute erlauben eine leerzeichengetrennte Liste von Werten, die zugewiesen werden können. Durch das Hinzufügen einer Tilde (~) vor dem Gleichheitszeichen wird dafür gesorgt, dass einer dieser Werte einen Treffer ergibt.

Folgendes Beispiel weist allen Absätzen mit einem Klassenattribut einen hellgelben Hintergrund zu, falls dieses den Wert attention hat.

  1. p[class~=attention]
  2. {
  3. background-color: #ffc;
  4. }

p[clss~=attention] ist also das selbe wie p.attention.

Nach oben

[Attr|=Wert]

Dieser Selektor ist für Attribute gedacht, deren Werte durch einen Bindestrich getrennt sind. Er dient hauptsächlich zum Gebrauch mit Sprachcodes. Der Vergleich beginnt am Anfang des Attributwertes.

Das folgende Beispiel trifft auf alle a-Elemente zu, deren Wert des hreflang-Attributes mit en beginnen. Das beinhaltet en, en-US, en-GB, en-cockney und jede andere en-Kombination.

  1. a[hreflang|=en]
  2. {
  3. background-color: #ffc;
  4. }

Mehrere Attributselektoren können auch kombiniert werden. Folgendes Beispiel weist nur einen hellgelben Hintergrund zu, wenn ein title-Attribut in einem a-Element vorhanden ist und das rel-Attribut zusätzlich den Wert external hat.

  1. a[title][rel~=external]
  2. {
  3. background-color: #ffc;
  4. }

Nach oben

CSS 3-Attributselektoren

CSS 3 fügt noch weitere großartige Attributselektoren hinzu. Dazu gehört ein Selektor um den Anfang des Attributwertes zu überprüfen E[Attr^=Wer], einen um Treffer am Ende des Attributwertes zu ermitteln E[Attr$=ert] und einen um auf Zeichenfolgen innerhalb des Attributwertes zu überprüfen E[Attr*=er].

Mozilla/Firefox und Opera kennen bereits all diese Attributselektoren, inklusive denen aus CSS 3. Der Internet Explorer 6 versteht keine Attributselektoren.

Nach oben

Pseudo-Selektoren

Pseudo-Selektoren werden dort eingesetzt, wo die Position eines Elementes nicht ausreicht um es anzusprechen, wie beispielsweise die erste Zeile eines Absatzes. Es gibt sowohl Pseudoelemente als auch Pseudoklassen, die uns auf Informationen außerhalb des Dokumentenbaumes zugreifen lassen.

Diesen Selektoren wird ein Doppelpunkt (:) vorangestellt. CSS 2.1 kennt vier Pseudoelemente: :first-line, :first-letter, :before und :after. Folgendes Beispiel erhöht die Schriftgröße des ersten Buchstaben im Absatz auf 2em:

  1. p:first-letter
  2. {
  3. font-size: 2em;
  4. }

Zudem kennt CSS 2.1 die :first-child-Pseudoklasse sowie zwei Pseudoklassen für Links (:link und :visited), drei dynamische Pseudoklassen (:active, :hover und :focus) sowie eine sprachspezifische Pseudoklasse (:lang).

Folgendes Beispiel färbt alle Links, die das erste Kindelement irgendeines Elements sind, grün ein:

  1. a:first-child
  2. {
  3. color: #090;
  4. }

Das nächste Beispiel färbt besuchte Links grün:

  1. a:visited
  2. {
  3. color: #090;
  4. }

Folgender Code setzt eine hellgelbe Hintergrundfarbe für Abschnitte auf französisch.

  1. p:lang(fr)
  2. {
  3. background-color: #ffc;
  4. }

Nach oben

Schlussfolgerung:

Ein mangelhaftes Verständnis von CSS-Selektoren mag nicht die einzige Erklärung für den Div-Wahnsinn sein, ist jedoch weitgehend dafür verantwortlich. Das div-Element mag nützlich für die Gruppierung und Positionierung des Inhaltes sein, aber CSS kann direkt auf Listen und andere Elemente, die eine akzeptable Bedeutung haben angewandt werden.

Kommentare ()

  1. Link zu diesem Kommentarpascal

    5. Juni 2005, 15:02 Uhr

    Heißt es nicht p::first-line, p::after usw? Das sind doch Pseudoelemente, die zwei Doppelpunkte benötigen…

  2. Link zu diesem KommentarBjörn

    5. Juni 2005, 16:55 Uhr

    @Eric
    Da warst Du wieder sehr fleißig. Sehr gute Arbeit.

    @Pascal
    Nein, Pseudoelemente benötigen nur einen Doppelpunkt.

  3. Link zu diesem KommentarMarkus

    9. Juni 2005, 08:01 Uhr

    Interessante Sache. Ich wusste gar nicht, dass es da so viele Selektoren gibt.
    Mach weiter so!

  4. Link zu diesem KommentarMiriam

    9. Juni 2005, 11:48 Uhr

    Ein schöner Überblick über ordentliches CSS. Jedoch finde ich wird nicht daraus klar wieso das zuerst aufgeführte Beispeil so schlimm ist.
    Wie sähe dies denn „richtiger“ aus? Ist dies überhaupt Browserübergreifend anders möglich?

    Vielen Dank
    Miriam

  5. Link zu diesem KommentarEric

    9. Juni 2005, 13:20 Uhr

    @Miriam: Das ist sogar relativ einfach Browserübergreifend möglich, in dem man beispielsweise Definitionslisten (dl) benutzt, ich werde in den nächsten Tagen ein Beispiel online stellen.

  6. Link zu diesem KommentarWolfram Heinz

    9. Juni 2005, 15:27 Uhr

    Hallo Eric,
    auch wenn Du „nur“ der Übersetzer bist, spreche ich Dich doch direkt an:
    Was mir an diesem Artikel fehlt, ist ein ganz konkretes und eindrucksvolles Beispiel, wie ich denn den „DIV-Wahnsinn“ durch geschickte Verwendung der CSS-Möglichkeiten loswerden kann.
    Wir verwenden beispielsweise geschachtelte DIVs (eben DIV-Wahnsinn), um einerseits über die jeweilige ID die DIV-Elemente ansprechen zu können und um andererseits die gemeinsamen Eigenschaften der DIV-Container nicht jedesmal neu definieren zu müssen, sondern DIV-übergreifend im CSS nur einmal.
    Beispiel:
    (Richtige Tags darf ich ja nicht verwenden; daher ohne Klammern)

    div id=“allgemeine DIVDefinition“
    div id=“spezielle DIVDefinition_1“
    bla
    /div
    div id=“spezielle DIVDefinition_2“
    bla
    /div
    div id=“spezielle DIVDefinition_3“
    bla
    /div
    /div

    Any comments or ideas would be appreciated!

    Gruß,
    Wolfram Heinz
    P.S: Bitte NICHT an den Webmaster schreiben. Es geht nicht um unsere Homepage – das ist nicht meine Baustelle!

  7. Link zu diesem Kommentarherojoker

    9. Juni 2005, 16:22 Uhr

    @Wolfram_Heinz:
    Verwende doch folgtendes im CSS:

    #spezDiv1, #spezDiv2, #spezDiv2 {
    // hier deine allgemeinen definitionen
    }

    #spezdiv1 {
    // div1-spezielles
    }

    ...

    HTH
    herojoker

  8. Link zu diesem KommentarWolfram Heinz

    9. Juni 2005, 16:48 Uhr

    Hallo herojoker,

    da bin ich baff! Frappierend einfach, aber so müßte es gehen!
    Irgendwie habe ich zu kompliziert gedacht ….

    Gruß,
    Wolfram

  9. Link zu diesem KommentarLogan

    10. Juni 2005, 14:35 Uhr

    das div wahn beispiel passt überhaupt nicht, ein besseres beispiel wäre eine navigation mit div elementen anstatt einer liste oder div anstatt address oder h1 oder für ne linie. der hauptgrund dass so viele divs benutzt werden sehe ich eher darin, dass die alternativen html-elemente nicht bekannt sind (divs sind ja einfach zu handhaben) und weniger in fehlendem wissen bei css-selektoren (von denen viele sehr schöne, z.b. attributabhängige, ja leider auch nicht browserübergreifend funktionieren).

    trotzdem für den der es nicht kennt eine gute zusammenfassung, weitermachen :-)