Um bestimmte html-Elemente anzusprechen, gibt es natürlich die einfache Möglichkeit, diesen html-Elementen (zB p-Absätzen oder div-Containern) eine ID oder Klasse zuzuweisen, und entsprechend im Stylesheet diese Klasse oder ID zu formatieren.
Gegebenfalls kann ich auch unzählige weitere Klassen formatieren und diese jedem html-Element zuweisen, sobald dies im Dokument erforderlich ist.
Es genügt meist völlig, übergeordnete html-Elemente mit einer Klasse oder ID anzusprechen; zB ein div Container, in denen sich zu formatierende p-Absätze befinden.
Doch man kann auch die Selektoren sehr effizient einsetzen, und so den übermässigen Gebrauch von Klassen zu vermeiden. Es hat auch etwas pragmatisches und fortschrittliches an sich, die Webseiten so übersichtlicher anzulegen.
Folgende Beschreibungen sind vielleicht nicht sofort eingängig, aber ich habe es bewusst darauf angelegt, mehr als nur ein paat beschreibende Sätze zu schreiben, sondern den Umgang praktisch zu veranschaulichen. Kurz gefasste Infos bieten ja andere Webseiten schon zu Genüge.
In der folgenden Illustration sind ineinander verschachtelte html-Elemente veranschaulicht (ob es korrekt ist, dass in einem blockquote-Element andere Elemente stehen, sei an dieser Stelle der Veranschaulichung halber mal vernachlässigt).
Je nachdem wie etwas verschachtelt ist, spricht man auch von Ebenen oder Hierarchien.
div#eins
<p>Textbeispiel... blah Text</p>
div
<p>Textbeispiel... blah Text</p>
<BLOCKQUOTE>
<p>Textabsatz</p>
<BLOCKQUOTE>
<p>Textabsatz</p>
<p>zweiter Textabsatz im grünen Container</p>
Beim roten und blauen
Behälter handelt es sich um
blockquote-Elemente, wobei der rote
Behälter in einem grauen
<div>-Container sich befindet.
Ich bezeichne im Folgenden die blockquote-Elemente der Übersicht halber
bloß als blaue oder rote Behälter.
In diesen Behältern befinden sich <p> Absätze.
Das alles befindet sich in einem übergeordneten grünen Container, und weitere <p>-Absätze sind an verschiedenen Stellen enthalten.
Man kann diese und andere html-Elemente ganz spezifisch ansprechen, ohne ihnen eine Klasse oder ID zuweisen zu müssen.
Hier ist der grüne Container der allumfassende Container, er trägt die ID mit dem Namen "eins", im styesheet als div#eins zu erkennen.
Zu beachten ist, dass der zweite blaue Behälter ein Kindelement von div#eins, und der rote Behälter nur ein Nachfahre von div#eins ist. Kindelemente folgen direkt, und Nachfahren folgen irgendwann. Das Kindelement wird mit > selektiert. Siehe Beispielseite 1.
Hierarchisch gesehen steht der graue Behälter zwischen div#eins und dem roten Behälter.
Es geht also um Ebenen und Hierarchien, was man sich am
besten für eine gegebene Webseite vergegenwärtigt, wenn man sich diese
Strukturen abstrakt denkt - wobei es immer ein html-Element gibt, das
an
oberster Stelle steht, das alle anderen html-Elemente enthält.
Wenn es kein <div>-Container ist,
dann ist
es der <body> der Webseite.
Für eine Formatierung, die den ganzen Bereich, also alle Ebenen im grünen Container und einschliesslich dieses grünen Containers betreffen, ist es eine einfache Situation. Ich verwende dann folgenden Selektor, um zum Beispiel eine Schriftfarbe festzulegen:
div#eins
Mit folgenden Selektor würde ich alle p
Textabsätze
ansprechen,
egal wo sie und auf welcher Ebene verschachtelt sie sich innerhalb
dieses umfassenden Containers (div#eins) befinden.
Die angesprochenen
Elemente müssen sich nur in diesem div#eins Container befinden:
div#eins p
Wenn ich nur die Textabsätze, die im grünen div#eins stehen, ansprechen will, aber den Text im grauen, roten und blauen Behälter ausschliessen will verwende ich den child-Selektor, der aus dem Zeichen > besteht:
div#eins > p
Nähere Erläuterung: Das p ist ein Kindelement von div#eins, aber der p-Absatz im roten Behälter ist nur Nachfahre, genauso wie der p-Absatz im blauen Container nur Nachfahre von div#eins ist. So würden mit dem child-Selektor div#eins > p der rote und blaue Behälter nicht angesprochen werden. Sie folgen sozusagen nicht direkt auf div#eins. Übrigens: Auch der zweite Textabsatz am unteren Rand des grünen Containers wird mit diesem Kind-Selektor angesprochen.
Um nur die Textabsätze im roten Behälter anzusprechen, ohne aber den p Absatz im blauen Behälter anzusprechen (ich kann in diesem Fall den einfachen Selektor blockquote nicht verwenden, da er beide Textabsätze innerhalb der blockquote-Elemente ansprechen würde!), benutze ich folgenden Selektor - denn der blaue Behälter, den ich ausschliessen möchte, befindet sich nicht in einem zusätzlichen div:
div#eins div blockquote p
Wenn ich
div#eins div p
benutze, dann werden alle Absätze in dem grauen Container angesprochen, also auch die im roten blockquote Behälter. Das p besagt in seinem Zusammenhang mit div#eins und div hier: egal in welcher Hierarchie und auf welcher Ebene, wenn ein p existiert, das nach dem div#eins folgt (bzw. in es verschachtelt ist) und nach einem weiteren div, so soll es angesprochen werden. Es könnten sich also noch andere html-Elemente zwischen div und p befinden, und das ist mit dem ersten blockquote-Element der Fall!
Wenn ich
div#eins div > p
verwende, schliesse ich dagegen den roten Behälter aus! Denn die Absätze im roten Behälter sind nur Nachfahren, aber kein direktes Kind von dem grauen Behälter. Und hier handelt es sich um einen Child-Selektor (Kind-Selektor).
Ein Kindelement folgt immer direkt hinter seinem Elternelement, bei einem Nachfahren sind andere html-Elemente sozusagen dazwischen geschaltet.
In der ersten Illustration ganz oben ist auch der zweite Textabsatz am unteren Rand des grünen Containers ein Kindelement des umfassenden div#eins-Containers.
Ein weiteres Kindelement des div#eins-Containers wäre der graue
div-Container. Div#eins ist in beiden Fällen das Elternelement.
Die Textabsätze im grauen,
roten und blauen
Kasten sind jedoch allesamt
nur Nachfahren und nicht Kind von div#eins.
Im folgenden Codebeispiel sind die ersten beiden <p>
Absätze Kindelement des <div>, auch <span>
ist Kindelement von <div>, aber das <em>
nicht.
<div>
<p></p>
<p></p>
<span></span>
<p><em></em></p>
</div>
<p>Vierter in diesem Beispiel auftauchender Absatz.</p>
<p>Das hier ist schon anders.</p>
Es kommt auch drauf an, wann ein html-tag geschlossen wird, womit ein weiterer besonderer Selektor zum Einsatz kommen kann: der Nachbar-Selektor, der aus dem Zeichen + besteht:
div + p
So kann ich konkret das erste Element ansprechen, das auf ein anderes folgt (es ist aber nicht zu verwechseln mit der Pseudoklasse :first-child).
Im obigen Beispiel den kursiv gestellten vierten Textabsatz, der auf das div folgt (nachdem der tag des div-Containers geschlossen wurde!), der letzte Absatz ("Das ist schon anders...") wird dagegen mit diesem sogenannten "Nachbar"-Selektor nicht angesprochen, und auch nicht der erste Absatz, der ja ein Kind des div ist, und kein Nachbar!
Um den ersten Absatz im grünen Container (<p>Textbeispiel... blah Text</p>) anzusprechen, und einen zweiten und alle folgenden Text-Absätze nicht anzusprechen (also jene Textabsätze <p>, die hierarchisch gesehen direkt hinter dem Container stehen), kann ich :first-child verwenden.
Zu Beachten ist, dass aber wirklich nur derjenige Textabsatz angesprochen wird, der das erste Kind-Element ist - wenn zum Beispiel eine Überschrift das allererste html-Element im div#eins Container ist, läuft dieser Selektor ins Leere.
div#eins p:first-child
Es ist sinnvoll, zu untersuchen und zu entscheiden, ob ich die Eigenschaften und Werte, die ich html-Elementen gebe, in einer Weise zuordnen kann, dass ich im Endeffekt nicht doppelt Eigenschaften und Werte verteilen muss.
Im folgenden werden alle p, die zugleich ein Nachfahre von div sind, und alle Klassen mit dem Namen "Bezeichnung" angesprochen und im stylesheet formatiert. Div p und die Klasse .bezeichnung erhalten dabei dieselbe Hintergrundfarbe.
div p, .bezeichnung { background-color: #776655; }
Ebenso kann ich bestimmte Eigenschaften wie margin etc. dann ebenso global verteilen, etwa in der Form:
p, ul, li { margin: 0; }
Ein Selektor wird spezifischer, wenn er mit weiteren html-Elementen verbunden wird.
.red { background-color: red; }
h1.red { background-color: orange; }
h2.red { background-color: green; }
Siehe zur Veranschaulichung Beispielseite 2 .
Wenn man zum Beispiel ein (dynamisches)
Navigationsmenü erstellt, kommt es oft vor, dass man mehrere li
Listen-Punkte gebraucht, die sich auf verschiedenen Ebenen
(hierarchisch gesehen) befinden.
Bei zwei Untermenüs ergibt sich
zB folgendes:
ul li ul li ul li
Das ist zB im Klartext:
ul li (Hauptmenü) ul li (1. Untermenü) ul
li (2. Untermenü)
Wenn man nun den dritten li Listenpunkt ansprechen will, genügt es: ul ul ul li als Selektor zu wählen.
Aber wenn man nun ul li ul li ul li formatiert hat, hat diese Formatierung eine höhere Spezifizität als wie ul ul ul li. Obwohl beide auf dasselbe Element zielen. DerSelektor mit niedriger Spezifizität wird dann nicht berücksichtigt.
Bei gleichen
Wertzuweisungen ist die höhere Spezifizität
immer ausschlaggebend.
Eine höhere Spezifizität
bedeutet, dass diese Angaben bevorzugt berücksichtigt werden.
Das heisst, wenn ich irgendwo
ul li ul li ul li { margin: 10px; }
formatiere, kann ich diese Formatierung des betreffenden Listenpunktes nicht mit
ul ul ul li { margin: 20px; }
überschreiben, selbst wenn letzterer Selektor erst an späterer Stelle im Stylesheet vorkommt!
Das ist ein Beispiel, wie es oft bei Navigationsmenüs vorkommt - es gibt aber noch reichlich andere Möglichkeiten in der Praxis, wo die Spezifizität wichtig werden kann.
Das macht so lange kein Problem, wie man eine Anweisung mittels eines Selektors gibt für den entsprechenden Bereich, der formatiert werden soll. Komplexe Seiten bedingen aber oft viele Selektoren und wenn man fest stellt, dass ein Selektor "nicht funktioniert", dann liegt es in den meisten Fällen einfach an der Spezifizität. Dann hilft oft nur noch, alle verschachtelten html-Elemente anzuführen, zB div#content div.box ul#inhalt li statt bloß ul#inhalt li usw.
Noch eine Besonderheit:
Wenn ich dem Textabsatz eine Klasse zuweise, zB mittels p.red,
und mit einer Eigenschaft formatiere (einen Wert zuweise), zB margin:
120px; - dann ist dieser Selektor (p.red) spezifischer,
und eine Formatierung des p
mit zB margin: 0px; wird
von p.red sozusagen
verdrängt.
Wenn ich aber p eine
Farbe zuweise, das aber nicht bei p.red
tue, dann gilt diese Eigenschaft der Farbe auch für alle
Textabsätze (p),
ungeachtet, ob diese p-Absätze Klassen oder ID zugewiesen werden.
Sofern diese Klassen oder ID nicht mit denselben
Eigenschaften formatiert werden (ein zugewiesener Wert ist ja immer
automatisch dabei) - wenn dieselben Eigenschaften formatiert werden,
hat die
Zuweisung von Wert durch die Klasse oder ID immer Vorrang).
Dass man zwei
verschiedene Anweisungen gibt, kann erfahrungsgemäß durchaus leicht
geschehen - vor allem,
wenn man conditional
comments
benutzt und aus irgendeinem (spontanen oder logischen) Grund heraus,
dann in diesen conditional comments eine andere Spezifizität benutzen
will, als wie man bereits auf der Webseite verwendet hat.
Dann sollte man bedenken,
welche Selektoren man bereits in welcher Form verwendet hat bzw. um die
Spezifizität wissen.
Oft verwendet man zu Korrekturzwecken der IE Versionen conditional comments - da kann es schon mal geschehen, dass man einen bestimmten Bereich mit verschiedenen Selektoren ansprechen will. Und wenn sich dann nichts tut, verzweifelt man oder wundert man sich, bis dass man um die höhere Spezifizität weiss.
Letztlich ergeben sich auch fortgeschrittene Einsatzmöglichkeiten der Selektoren. Auch eine einfache Kurzschrift ist nun möglich (der Verwendung von Selektoren), bei der man genau weiss, welche Bereiche angesprochen werden und welche nicht.