barrierefreies Webdesign Ingo Turski

zum Inhalt

Ingo

Tips und Tricks:Dynamische Navigationsleisten mit CSS (JavaScript für den IE)

Ein Menü mit mehreren Navigationsebenen ist eine Auflistung von Links, jedoch keine sequentielle. Es sollte als verschachtelte Liste ausgezeichnet werden, um die logische Struktur auch ohne CSS abzubilden:

<ul>
  <li><a href="#">Item one</a>
    <ul>
      <li><a href="#">Subitem one</a></li>
      <li><a href="#">Subitem two</a></li>
      <li><a href="#">Subitem three</a></li>
      <li><a href="#">Subitem four</a></li>
    </ul>
  </li>
  <li><a href="#">Item two</a></li>
  <li><a href="#">Item three</a></li>
  <li><a href="#">Item four</a></li>
</ul>

Eine so verschachtelte Liste läßt sich auch geteilt darstellen, so daß die Menüpunkte der ersten Ebene horizontal in einer Reihe und die der zweiten Ebene vertikal passend darunter angeordnet werden. Moderne Browser ermöglichen darüber eine dynamische Navigation, in der die Unternavigation erst beim Überfahren der dazugehörigen Hauptmenüpunkte eingeblendet werden:

Weiter unten finden Sie diese Liste übrigens auch vertikal formatiert.

Um ein dynamisches Einblenden der Unternavigation auch im Internet Explorer 6 (der den Zustand :hover nur auf <a>-Elemente mit dem Attribut "href" anwenden kann und diese nicht ineinander verschachtelt werden dürfen) zu ermöglichen, bleibt Ihnen derzeit nur eine Realisierung über JavaScript: aktivieren Sie das vorbereitete Script - allerdings nur im Internet Explorer, da es in modernen Browsern zu unschönen Effekten durch Überlagerung mit der CSS-Dynamik kommt.

Der HTML-Quelltext war geringfügig zu erweitern. Ein zusätzliches, um die Navigationsleiste gesetztes <div> dient zur Definition einer ausreichend große Breite, um einen Umbruch zu verhindern und die richtige Reihenfolge der angezeigten Menüpunkte zu gewährleisten, sowie zur browserübergreifend korrekten Rahmen- und Hintergrundgestaltung. Als Element ohne semantische Bedeutung hat es ohne CSS keine Auswirkung auf die Darstellung. Die Listenpunkte der ersten Ebene sind über float aus dem Elementfluss genommen, der über ein innerhalb dieses Rahmens eingefügtes leeres <div>-Element mit der CSS-Eigenschaft clear wieder hergestellt wird.
Der aktuelle Menüpunkt ist hier nicht verlinkt, sondern mit dem Element <span> ausgezeichnet und wird gesondert formatiert. Um auch den dazugehörigen Menüpunkt der ersten Ebene über CSS hervorheben zu können, wird für diesen die id="aktuell" angegeben.

Die verschachtelte Liste ist mit position:absolute leicht überlappend unter den Listenpunkt der ersten Ebene gesetzt, damit sich li:hover auch für die Unternavigation auswirken kann. Für die Listenpunkte hierin ist float aufgehoben und statt dessen display:block definiert.

Neu ist, daß die Breite der Menüpunkte nicht für <li> angegeben wird, sondern für die hierin enthaltenen Elemente. Diese nach CSS 2.1 gültige Möglichkeit, float ohne Angabe von width zu verwenden, beseitigt auch Browserprobleme, z.B. beim Opera 7 die fehlerhafte Umsetzung der dynamisch geänderten CSS-Eigenschaften.

Eine solche dynamische Navigationsleiste ist praktisch einsetzbar, wenn Sie die Menüpunkte der ersten Ebene mit Übersichtsseiten verlinken, die neben Verweisen auf die Menüpunkte der Unternavigation auch eine Einleitung zur jeweiligen Rubrik enthalten können. Somit wird die Navigation für ältere Browser, den Internet Explorer 6 bei deaktiviertem JavaScript und auch einer Tastatursteuerung zugänglich gemacht.

Nachfolgend nun der komplette Quelltext für die dynamische Navigationsleiste. Beachten Sie, daß der Internet Explorer 6 über den verwendeten DOCTYPE in den standard-kompatiblen Modus versetzt wird und für den 'quirks mode' die im CSS kommentierten Zeilen zu löschen sind.
Das JavaScript wird über eine Browserweiche (Abfrage der Spracheinstellung) nur dem Internet Explorer für Windows und Macintosh zugänglich gemacht; wenn Sie den MAC-IE vernachlässigen, können Sie das gesamte Script auch in den (hier blau markierten) 'conditional comment' setzen und auf die Browserweiche verzichten.
Die Funktion hoverIE() wird vom Script selbst onload aufgerufen und erfordert keine weiteren Änderungen am HTML-Quelltext. Sie ist auf die Erfordernisse der verwendeten Struktur reduziert, so daß zusätzliche in die Listenpunkte eingefügte Elemente eine Anpassung erfordern.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
<head>
<title>Dynamische Navigationsleiste</title>

<style type="text/css">
  div#Tmenu {
    font-size: 94%;
    width: 39.8em;
    padding: 0.8em;
    border: 1px solid white;
    background-color: #eee;
  }
  * html div#Tmenu {
    width: 41.4em;
    w\idth: 39.8em;  /* IE 6 in standards-compliant mode */
  }
  div#Tmenu div {
    clear: left;
  }
  ul#Navigation {
    margin: 0; padding: 0;
    text-align: center;
  }

  ul#Navigation li {
    list-style: none;
    float: left;
    position: relative;
    margin: 0.4em; padding: 0;
  }
  * html ul#Navigation li {
    margin-bottom: -0.4em;
  }

  ul#Navigation li ul {
    margin: 0; padding: 0;
    position: absolute;
    top: 1.7em; left: -0.4em;
  }
  * html ul#Navigation li ul {
    left: -1.5em;
    lef\t: -0.4em;
  }
  ul#Navigation li ul li {
    float: none;
    display: block;
    margin-top: 0.2em; margin-bottom: 0.2em;
  }

  ul#Navigation a, ul#Navigation span {
    display: block;
    width: 7em;
    font-family: "Trebuchet MS", "Century Gothic", Helvetica, Arial, sans-serif;
    text-decoration: none; font-weight: bold;
    padding: 0.23em 0.97em 0.17em 1.03em;
    border: 1px solid #600;
    border-left-color: #ea0; border-top-color: #ea0;
    color: white; background-color: #c00;
  }
  * html ul#Navigation a, * html ul#Navigation span {
    width: 9.2em;
    w\idth: 7em;  /* IE 6 in standards-compliant mode */
  }
  ul#Navigation a:hover, ul#Navigation span, li a#aktuell:hover {
    padding: 0.17em 1.03em 0.23em 0.97em;
    border-color: #ea0;
    border-left-color: #900; border-top-color: #900;
    background-color: #e00;
  }
  ul#Navigation li ul a:hover {
    border-color: #900;
  }
  li a#aktuell {
    border-right-color: #300; border-bottom-color: #300;
    background-color: #900;
  }
  ul#Navigation li ul span {
    border-right-color: #c96; border-bottom-color: #c96;
    color: #900; background-color: white;
  }
  ul#Navigation li a:active, ul#Navigation li:hover a:active {
    color: black; background-color: #f00;
  }

/* dynamisches Ein-/Ausblenden */
  ul#Navigation li ul {
    display: none;
  }
  ul#Navigation li:hover ul {
    display: block;
    background: #eee;
  }
</style>

<!--[if IE]>
<script type="text/javascript">
// <![CDATA[
if(window.navigator.systemLanguage && !window.navigator.language) {
  function hoverIE() {
    var LI = document.getElementById("Navigation").firstChild;
    do {
      if (sucheUL(LI.firstChild)) {
        LI.onmouseover=einblenden; LI.onmouseout=ausblenden;
      }
      LI = LI.nextSibling;
    }
    while(LI);
  }

  function sucheUL(UL) {
    do {
      if(UL) UL = UL.nextSibling;
      if(UL && UL.nodeName == "UL") return UL;
    }
    while(UL);
    return false;
  }

  function einblenden() {
    var UL = sucheUL(this.firstChild);
    UL.style.display = "block"; UL.style.backgroundColor = "#eee";
  }
  function ausblenden() {
    sucheUL(this.firstChild).style.display = "none";
  }

  window.onload=hoverIE;
}
// ]]>
</script>
<![endif]-->

</head>
<body>

<div id="Tmenu">
  <ul id="Navigation">
    <li><a id="aktuell" href="#Beispiel">Seite 1</a>
      <ul>
        <li><span>aktuelle Seite</span></li>
        <li><a href="#Beispiel">Seite 1b</a></li>
        <li><a href="#Beispiel">Seite 1c</a></li>
        <li><a href="#Beispiel">Seite 1d</a></li>
      </ul>
    </li>
    <li><a href="#Beispiel">Seite 2</a></li>
    <li><a href="#Beispiel">Seite 3</a>
      <ul>
        <li><a href="#Beispiel">Seite 3a</a></li>
        <li><a href="#Beispiel">Seite 3b</a></li>
        <li><a href="#Beispiel">Seite 3c</a></li>
      </ul>
    </li>
    <li><a href="#Beispiel">Seite 4</a></li>
  </ul>
  <div></div>
</div>

</body>
</html>

Wenn Sie unter 'dynamisches Ein-/Ausblenden' den Kindsselektor verwenden, also ul#Navigation li>ul {display:none;} notieren, dann wird die Unternavigation nur von modernen Browsern ausgeblendet und steht somit auch älteren Browsern ohne JavaScript zur Verfügung - dies jedoch ständig!

Mit geringfügigen Änderungen am CSS läßt sich diese Navigationsliste auch vertikal darstellen. Die Untermenüpunkte müssen dann allerdings auf jeden Fall ausgeblendet werden, da sie sich sonst überlagern würden.
Da hier kein float verwendet wird, ist im HTML das clearende leere <div></div> nach der Liste nun überflüssig.
Die <ul> der Unternavigation wird hier unmittelbar neben den Listenpunkt der Hauptnavigation positioniert und die <li> der Unternavigation mittels padding-left auf Abstand gebracht, damit keine Lücke zwischen den Elementen entsteht und sich die Unternavigation nicht vorzeitig schließt. Im Gegensatz zu vielen anderen Menüs dieser Art kann die Unternavigation dadurch auch leicht diagonal angesteuert werden.

<style type="text/css">
/* Vertikale Navigation */
  div#Tmenu {
    font-size: 94%;
    width: 10em;
    padding: 0.8em;
    border: 1px solid white;
    background-color: #eee;
  }
  * html div#Tmenu {
    width: 11.3em;
    w\idth: 10em;  /* (IE 6 in standards-compliant mode) */
  }
  ul#Navigation {
    margin: 0; padding: 0;
    text-align: center;
  }

  ul#Navigation li {
    list-style: none;
    position: relative;
    margin: 0.4em; padding: 0;
  }
  * html ul#Navigation li {
    margin-right:1.5em;  /* Platz fuer Link-Verbreiterung im IE reservieren */
    margin-bottom:0;
  }

  ul#Navigation li ul {
    margin: 0; padding: 0;
    position: absolute;
    top: 0; left: 9em;
  }
  ul#Navigation li ul li {
    margin: 0; padding-left: 1.4em;
  }

  ul#Navigation a, ul#Navigation span {
    display: block;
    width: 7em;
    font-family: "Trebuchet MS", "Century Gothic", Helvetica, Arial, sans-serif;
    text-decoration: none; font-weight: bold;
    padding: 0.2em 1em;
    border: 1px solid #900;
    border-left-color: #c96; border-top-color: #c96;
    color: white; background-color: #c00;
  }
  * html ul#Navigation a, * html ul#Navigation span {
    width: 9em;
    w\idth: 7em;  /* (IE 6 in standards-compliant mode) */
  }
  ul#Navigation a:hover, ul#Navigation span, li a#aktuell:hover {
    border-color: #c96;
    border-left-color: #900; border-top-color: #900;
    background-color: #e00;
  }
  li a#aktuell {
    border-right-color: #300; border-bottom-color: #300;
    background-color: #900;
  }
  ul#Navigation li ul span {
    border-color: #900; border-left-color: #c96;
    color: #900; background-color: white;
  }
  ul#Navigation li a:active {
    color: black; background-color: #f00;
  }

/* dynamisches Ein-/Ausblenden */
  ul#Navigation li ul {
    display: none;
  }
  ul#Navigation li:hover>ul {
    display: block;
  }
  ul#Navigation>li:hover>a {
    width: 8.2em;
    background: #e00 url(pfeil.gif) no-repeat center right;
  }

/* dynamisches Ein-/Ausblenden der JavaScript-generierten Klasse im IE */
  * html ul#Navigation li.hoverIE {
    margin-right:0;  /* reservierten Platz freigeben */
    margin-bottom:-1.15em;  /* Fehlerkorrektur, ggfls. anpassen */
  }
  * html ul#Navigation li.hoverIE ul {
    display: block;
  }
  * html ul#Navigation li .hoverIE {
    width: 10.3em;
    w\idth: 8.2em;  /* (IE 6 in standards-compliant mode) */
    background: #e00 url(pfeil.gif) no-repeat center right;
  }
</style>

Zur besseren Orientierung werden die Listenpunkte der Hauptnavigation bei :hover verbreitert und mit einer in den zusätzlichen Raum positionierten Hintergrundgrafik versehen. Der Internet Explorer ist nicht in der Lage, dies exakt umzusetzen. Für eine ähnliche Darstellung benötigt er umfangreiche andere CSS-Definitionen, wozu eine Klasse über die JavaScript-Funktionen hinzugefügt wird:

  function einblenden() {
    this.className="hoverIE"; this.firstChild.className="hoverIE";
  }
  function ausblenden() {
    this.className=""; this.firstChild.className="";
  }

Ausführliche weitere Beschreibungen finden Sie im neuen Kapitel 'CSS-basierte Layouts' der SELFHTML-Dokumentation unter CSS-basierte Navigationsleisten.