Frank Rohse 5. Februar 2006

Tutorial: Das perfekte Menü – Klappmenü: Navigieren in Dimensionen

Kein Beitragsbild

Frank war Mitarbeiter im Dr. Web Team in unserer Ahrensburger Zeit. Später...

Wenn die Webseite wächst und gedeiht und die vielen Seiten beim besten Willen nicht mehr aufgereiht in eine Menüleiste passen, greifen Webdesigner gern zum praktischen Ausklappmenu. Die Unterpunkte werden versteckt und erscheinen erst bei Maus-Kontakt.

Credits: Claire Campbell und Peter Nederlof

Das Modell unseres Ausklappmenu-Platzwunders funktioniert mit reinem CSS, also ohne JavaScript und ist deshalb suchmaschinenfreundlich und barrierearm zugleich. Den Browser-Veteranen aus der Internet-Explorer-Familie machen wir das Menu mit Conditional Comments und IE Behaviors schmackhaft. Ein bisschen CSS zaubert die horizontale und vertikale Version des Menus aus dem gleichen HTML-Quelltext.

Snazzy Borders Screenshot
Platzwunder Ausklappmenu in Aktion

Live Demo im neuen Fenster: 2D-Ausklappmenu vertikal und – horizontal

Den IE vergessen ist vermutlich gößter Wunsch fast aller CSS-Designer. Damit uns die Darstellungseigenheiten der Microsoft-Browser beim standardbasierten Konstruieren unseres Ausklappmenus nicht weiter in die Quere kommen sortieren wir sie mit Conditional Comments aus. Der folgende Code-Block kommt in den <head>, den IE müssen wir dann für dieses Projekt nicht weiter spezialbehandeln.

  <!--[if IE]>
    <style type="text/css" media="screen">
    #menu ul li {float: left; width: 100%;}
    </style>
    <![endif]-->

    <!--[if lt IE 7]>
    <style type="text/css" media="screen">
    body {behavior: url(csshover.htc); font-size: 100%;}
    #menu ul li a {height: 1%;}
    }
    </style>
    <![endif]--> 

Wichtigster Bestandteil ist die oben verlinkte Datei csshover.htc. Das kleine Stückchen Jscript(!) übersetzt dem Internet Explorer <hover> Anweisungen und sorgt für korrekte Ausführung. Der Autor des Scripts Peter Nederlof hat nähere Angaben zu Funktion und Einsatz.

Mit float, width und height bringen wir den Explorern bei unsere <ul> ordentlich darzustellen (Whitespace Bug).

Kern unserer Navigation ist wieder einmal eine <ul>.

       <div id="menu">
    <ul>
    <li><h2>Titel 1</h2>
      <ul>
      <li><a href="#">eins</a></li>
      <li><a href="#">zwei ...</a>
        <ul>
        <li><a href="#">zwei a</a></li>
        <li><a href="#">zwei b</a></li>
        <li><a href="#">zwei c</a></li>
        <li><a href="#">zwei d</a></li>
        </ul>
      </li>
      <li><a href="#">drei ...</a>
        <ul>
        <li><a href="#">drei a</a></li>
        <li><a href="#">drei b ...</a>
          <ul>
          <li><a href="#">drei
    b i</a></li>
          <li><a href="#">drei
    b ii</a></li>
          <li><a href="#">drei
    b iii</a></li>
          </ul>
        </li>
        <li><a href="#">drei c</a></li>
        </ul>
      </li>
      </ul>
    </li>
    </ul>
    </div> 

Hier kommt es auf die sorgfältige Verschachtelung der Listen an. Die nächste Menuebene kommt stets in das <li> Element der Ebene darüber. Alle Einträge unter Titel 1 sind in einer <ul> mit einem einzigen <li>. Weitere Hauptmenu-Punkte (Titel 2, Titel 3 usw) werden genauso konstruiert und aneinandergereiht (hier nicht abgebildet).

Zum Schluß setzen wir das komplette Menu auf einer HTML-Seite in ein <div id=“menu“>.

Das HTML-Grundgerüst stylen wir für die vertikale Menu-Version mit CSS wie folgt:

       #menu { width: 80px; background: #eee; } 

    #menu ul { list-style: none; margin: 0; padding: 0; } 

    #menu a, #menu h2 {
      font: bold 11px/16px arial, helvetica, sans-serif;
      display: block;
      border-width: 1px; border-style: solid; border-color: #ccc #888
    #555 #bbb;
      margin: 0; padding: 2px 3px; }

    #menu h2 { color: #FF8635; background: #96D12C; text-transform: uppercase;
    } 

    #menu a { color: #000; background: #efefef; text-decoration: none; } 

    #menu a:hover { color: #a00; background: #fff; } 

Hier legen wir die Breite der Menu-Einträge (80px), Schriftart, Rahmen-, Text- und Hintergrundfarben fest und schalten die Listenzeichen ab. Mit der Zeilenhöhe (16px) regulieren wir die Höhe der Einträge. display: block sorgt dafür, dass Titel und Links stets die ganze Breite ausfüllen.

Bleiben noch Fragen der Positionierung zu klären:

      #menu li { position: relative; }

    #menu ul ul ul {position: absolute; top: 0; left: 100%; width: 100%; }

    div#menu ul ul ul, div#menu ul ul li:hover ul ul {display: none;} 

    div#menu ul ul li:hover ul, div#menu ul ul ul li:hover ul {display: block;}
    

Dank dem mit Bedacht gewählten position: relative für alle <li> im Menu positionieren wir die <li> im folgenden stets relativ zum übergeordneten Element. Ein #menu ul ul ul {position: absolute; top: 0; left: 100%; width: 100%; } sorgt dann dafür, dass alle <ul> die zwei Ebenen tief in anderen <ul> verschachtelt sind rechtsbündig neben dem direkt übergeordneten Element erscheinen.

Jetzt haben unsere Menupkte die richtige Position, aber es sind alle auf einmal sichtbar! Im nächsten Schritt verstecken wir deshalb alle außer den ersten beiden Ebenen wieder: ul ul ul {display: none;}. Gleichzeitig verstecken wir auch die Einträge, die beim hover Event eventuell noch auf der zweiten Ebene darunter liegen: ul ul li:hover ul ul {display: none;}

Kurz danach machen wir die einfach und zweifach verschachtelten Folge-Listen beim hovern über das zugehörige <li> wieder sichtbar: div#menu ul ul li:hover ul, div#menu ul ul ul li:hover ul {display: block;} – erledigt.

Snazzy Borders Screenshot

Das gleiche Menu auf horizontal gestylt

Ohne weiteres können wir den gleichen HTML-Quelltext nun auch auf horizontal trimmen. Hierzu das nötige CSS auf einen Blick:

     #menu { width: 100%; background: #eee; float: left; }

    #menu ul { list-style: none; margin: 0; padding: 0; width: 80px; float: left;
    } 

    #menu a, #menu h2
      { font: bold 11px/16px arial, helvetica, sans-serif;
      display: block; border-width: 1px; border-style: solid;
      border-color: #ccc #888 #555 #bbb;
      margin: 0; padding: 2px 3px; } 

    #menu h2 { color: #FF8635; background: #96D12C; text-transform: uppercase;
    } 

    #menu a { color: #000; background: #efefef; text-decoration: none; }

    #menu a:hover { color: #a00; background: #fff; }

    #menu li {position: relative;} 

    #menu ul ul { position: absolute; z-index: 500; }

    #menu ul ul ul { position: absolute; top: 0; left: 100%; } 

    div#menu ul ul,
    div#menu ul li:hover ul ul,
    div#menu ul ul li:hover ul ul
      {display: none;} 

    div#menu ul li:hover ul,
    div#menu ul ul li:hover ul,
    div#menu ul ul ul li:hover ul
      {display: block;} 

Diesmal soll das Menu die ganze Bildschirmbreite füllen: menu {width: 100%};. Menu und Haupteinträge hätten wir gerne linksbündig nebeneinander aufgereiht: float: left. Unterschiede im CSS gibt es dann bis #menu li {position: relative;} nicht mehr.

Einträge auf der zweiten Ebene erscheinen in der horizontalen Version erst bei Mausberührung. Sie erscheinen ohne weitere Positionierungsangabe unter dem übergeordneten Eintrag. Ein #menu ul ul {position: absolute; z-index: 500;} ist deshalb alles was wir hier noch brauchen. Der z-index Wert stellt sicher, dass unser Menu über eventuell darunter liegendem Text erscheint.

Das Prinzip der mit display: none versteckten und mit display: block partiell wieder sichtbar gemachten Einträge ist identisch. Weil in der horizontalen Version die zweite Menuebene erst beim hovern sichtbar wird, müssen wir die einfach verschachtelten Listen in der zweiten Ebene div#menu ul ul, div#menu ul li:hover ul ul {display: none;} und div#menu ul li:hover ul {display:block;} berücksichtigen.

Das Menu beherrscht in der jetztigen Version drei Ebenen. Für jede zusätzlich gewünschte Ebene ist das entsprechendes Selektorenpaar bei display: none und display:block hinzuzufügen.

Getestete Browser: IE Mac/Win ab 5.5, Firefox, Mozilla, Opera ab 7.1, Netscape ab 6.0

Frank Rohse

Frank war Mitarbeiter im Dr. Web Team in unserer Ahrensburger Zeit. Später machte er sich als Webdesigner mit Schwerpunkt CSS und Barrierearmut selbständig.

55 Kommentare

  1. Hallo @all,

    ich habe ein Problem mit dem Tutorial. Die Navigation wird nicht horizontal, es bleibt vertikal. Ich habe den HTML5 Tag benutzt statt der

    Kann mir jemand helfen? :-/

  2. mittlerweile liest das hier vielleicht keiner mehr aber ich frage trotzdem: wie erreicht man, dass die horizontale navigation – übrigens wunderbar und einfache gemacht. kompliment! – auf einer webseite mittig erscheint?

  3. Hallo,

    Ich möchte bei dieser Webseite gerne das horizontalmenu so ausrichten, dass Unterkategorien nach oben ins Bild klappen. Habe das schon auf mehreren Seiten gesehen, aber weiß nicht wie man das macht. Vielleicht kann mir jemand eine Anleitung dazu geben. Die Untermenüs müßte ich im HTML erst erstellen.

    mit freundlichen Grüßen

    Ferdinand Senfter

  4. Pingback: "Dropdown"-men
  5. Hi!
    @kaend, du hast das hier in deiner style.css:
    div#menu ul ul,
    div#menu ul li:hover ul ul,
    div#menu ul ul li:hover ul ul {display: none;}

    div#menu ul li:hover ul,
    div#menu ul ul li:hover ul,
    div#menu ul ul ul li:hover ul {display: block;}

    für jedes weitere untermenü mußt du die zeilen erweitern:
    div#menu ul ul,
    div#menu ul li:hover ul ul,
    div#menu ul ul li:hover ul ul {display: none;}
    div#menu ul ul li:hover ul ul ul {display: none;}

    div#menu ul li:hover ul,
    div#menu ul ul li:hover ul,
    div#menu ul ul ul li:hover ul,
    div#menu ul ul ul ul li:hover ul {display: block;}

    mfg Andi

  6. Pingback: Links aus Submen
  7. hallo,

    wenn man mehr als 3 ebenen hat, was muss man ändern um auch die nachfolgenden langsam einblenden zu lassen?

    so wird ab der 3ten ebene sofort alles darunterliegende mit eingeblendet, was ich so irgendwie nicht will – nur komm ich nicht dahinter was ich ändern muss 🙂

    danke schon mal für eure hilfe

    lg kaend

  8. Hy Leute,
    Eure Seite ist wirklich prima !!!
    Ich bin Neuanfänger und Quereinsteiger und wusste vor 7 Monaten noch nix von HTML, CSS, PHP usw…
    Eure Codes sind auf das Essentielle reduziert. Das gefällt mir besonders ! Hab schon etliche Versionen ausprobiert (teils mit Hilfe von Java). Der unschlagbare Vorteil Eurer Version: „In der Kürze liegt die Würze“. Nach dem Motto „weniger ist mehr !“ So müssen Codes und Scipts aussehen: übersichtlich und mit einem Minimum an Aufwand ein Maximum an Funktionalität !!!
    Das Problem mit dem IE (welche Version auch immer) ist doch normal.
    Er stammt von Microsoft :-). Die lernen es nie mit der Zeit zu gehn und sich anzupassen. Die glauben doch immer noch die Standards diktieren zu können. Bill Gates war zwar ein guter Kaufmann aber ein lausiger Programmierer, deswegen hat er sein erstes DOS, was er an IBM verscheuert hat, ja auch von einem anderen gekauft !!!
    Ich passe mich mit meinen Seiten nicht dem IE an. So unterstütze und verlängere ich ja das Problem nur. Ein dezenter Link auf der Site zum kostenlosen Download anderer Browser scheint mir da sinnvoller.
    …jetzt aber genug der Philosophie 🙂
    Weiter so Leute und Viiiiielen Dank
    MfG
    Jürgen

  9. Hallo Zusammen,

    gibt es eine Möglichkeit aufgeklappte Menüs nach dem Click wieder in den Ausgangszustand zurück zu bringen? Das wäre nützlich, wenn eine Menüfunktion keine neue Seite aufruft (und somit ein re-Layout anstößt) sondern beispielsweise eine javascript Funktion ausführt. Dann sollte sich das Menü wieder schließen, sodass der Benutzer erkennt, dass die Funktion ausgeführt wird. In der aktuellen Ausführung geht das leider nicht.

    Grüße
    Markus

  10. Hi,
    um auf meinen Vorschreiber zurückzukommen: Gibt es eine Lösung für den IE8???

    Leider kann man den wie oben versprochen nicht komplett vergessen. Würde mich sehr über eine Lösung freuen.

    Danke,!

  11. Hey,
    schön erklärt soweit. Ich kannte den Kram auch vorher schon. Funktioniert mit Firefox auch. Aber im IE geht gar nichts. Will einfach nicht hovern. Hab das mal eins zu eins übernommen und auch die aktuellste .htc geladen. Hovert einfach nicht.
    Gern auch per Mail: bbg14@gmx.de

    @Vorposter: Geh mal auf die Seite meiner Firma: http://www.dbsystel.de
    Dieses Menü dort ist vom Prinzip ähnlich aufgebaut, jedoch wird dort die Navi einfach neugeladen bei einem Seitenaufruf. Untermenüs werden also je nach aufgerufener HTML Seite eingeblendet. Ist nützlich, aber da ich mit PHP arbeite keine Lösung für mich.

    Edit: Es dauert seine Zeit, bis man sich bei der o.g. Seite durch die ganzen Klassen gewühlt hat. Aber sie sind einleuchtend. Wenn du Fragen dazu hast, kontaktier mich.
    Zur Erschließung des Quelltextes empfehle ich das Addon Firebug für Firefox.

    Edit 2: Nach 2 Wochen gehts nun doch. Dieser verfluchte Doctype. Hatte den falschen Link drin.

  12. Hallo,

    ich suche auch schon seid langem nach einem Menü, dass ich für die unterschiedlichsten Anwendungen verwenden kann.
    Da ist dieses hier genau richtig. Allerdings habe ich trotz aller Freude noch ein Problem.
    Wie kriege ich es hin, das die Submenüs aufgeblendet bleiben, wenn ich das Menü verlasse??? Zweck davon ist, zu sehen, welcher Menüpunkt gerade aktiv ist.

    Danke für eure Hilfe ! ! !

  13. Pingback: Valides Listenmen
  14. Servus ,mit Firefox klappt alles prima aber beim Internet Explorer ist alles versetzt, wo muß ich diese Datei > csshover.htc genau hinzufügen.
    Gruß

  15. Bei den Seiten Preise, Pauschalen und Informationen ist das Untermenu nach rechts verschoben? Viel probiert nichts gefunden warum es so ist?
    Danke für die Hilfe.

  16. Hallo!!

    ich brauche hilfe!!

    habe schon mehrere menüs probiert, alle funktionieren in Firefox aber in IE 8 klappt keiner auf (passiert es nix).

    hat jemand ein trick für IE 8 gefunden?

    danke schön!

  17. Hi, ich habe ein kleines abe rdoch blödes Problem.
    Das Menu klappt in allen Browsern super auch dann wenn man die Schrift vergrößert. Echt top, nur der ie7 macht hier irgendwie mist.

    Wenn die Schrift vergrößert wird (barrierefrei und so) dann bleibt die Schrift im Menu gleich super gut doch der ie7 macht auf einmal zwischen den submenu Teilen immer 1-3 px dazwischen so das ich nicht bis zu untern Bereich scrollen kann. denn der ie7 meint dann der zwischenabstand zwischen sub sub Menu ist zu groß und schliesst das ganze einfach.

    Was kann ich machen?
    gruß
    Freue mich Antworten mit einer Lösung zu bekommen, denn auf der htc Seite finde ich hierzu auch keine Antwort

  18. Gibt’s die Möglichkeit, dass das Submenu rechts ausgeklappt bleibt, wenn ich auf einer Unterseite bin? Habe einiges rumprobiert, aber dann rutschen die Menülinks im 1.Level alle nach unten.

  19. Habe schon lange ein Klappmenü gesucht und wollte schon aufgeben.
    Mein CSS funktioniert nach einigen testen.
    Ein schlichtes, einfach verständliches code-Grundgerüst.
    Damit kann man echt schicke Navileisten zaubern.

    Vielen Dank!!!!!!!!!!!
    habt mir echt weitergeholfen

  20. hallo!

    die lösung hierzu:

    Wie krieg ich das hin, dass Titel 1, Titel 2 usw auch einen Link bekommen?
    Wenn ich da einfach [] hinzufüge, wird das komisch dargestellt, weil das im Stylesheet ja so angegeben wurde.
    Hab ein bisschen rumexperimentiert, bin aber noch zu keinem Ergebnis gekommen.

    interessiert mich auch!

    bitte gebt mir nen tip!

  21. Super Script! Danke!

    @eWings und @miklos:
    Habt ihr den DOCTYPE vergessen einzubauen?

    Im IE 8 hatte das Script auch nicht geklappt, da ich den DOCTYPE vergessen hatte. *schäm*

    Gruß

    poah

  22. Die Navigation funktioniert sehr flüssig.

    Nach ein wenig Herumprobieren, klappt auch alles perfekt im Internet Explorer (Tipp: ich habe # menu width in 100$ angegeben.

    Wenn jemand bzgl. des IE Probleme hat, kann er mir gern eine E-Mail (leeser@gmx.de) schreiben und ich werden helfen.

  23. Noch ne Frage:
    Wie schafft man es, dass die Links die einen zu dem aktuell ausgewählten Link geführt haben, aufleuchten, als währen sie gerade ausgewählt.

    Ich hoffe diese Frage ist irgendwie verständlich 🙂

  24. Hallo,
    echt suuuuper Script. Aber eine Frage habe ich noch:

    Wie stellt man es so ein, dass zwar zwischen den verschiedenen Listeneinträgen Platz ist, nicht aber zwischen mehreren zeilen, wenn diese zu dem selben Eintrag gehören?

    Danke im Voraus

    Paul-Georg

  25. Hallo,

    hat bei mir alles soweit einwandfrei funktioniert. Jetzt hab ich nur das Problem das im Firefox alles hervorragend aussieht, jedoch im InternetExplorer nix funktioniert.
    !!!HELP!!!
    csshover3.htc hab ich auch schon versucht. Brachte aber leider keinen Erfolg.
    Woran könnte es noch liegen?

    Gruß, der eWinG

  26. Hallo,

    finde das Script auch sehr super, funktioniert alles. Ich habe die horizontale Version angewendet. Ich möchte allerdings, das die Texte von den Links zentriert stehen. Im Firefox kein Problem (hab #menu mit text-align:center erweitert). Wenn ich mir das Ganze dann im Explorer anschaue, verschieben sich die ausklappbaren Unterlinks beim Hover nach rechts. Sie stehen also nicht genau unter dem Elternlink, sondern genau zwischen zwei Elternlinks. Ich hab keine Ahnung, wie ich das hinbekomme… Bitte helft mir! Danke.

  27. Pingback: Men
  28. Hi Tim, versuch mal dem frame die Eigenschaft
    style=“overflow: visible“ zu geben… müsste funktionieren =)
    Hoffe ich konnte helfen.

    Das Menü ist wirklich perfekt =D
    Auch die Erklärung der Funktionsweise und Attribute ist toll!
    Vielen Dank!

  29. Pingback: Pulldown Men
  30. Pingback: horizontales Men
  31. Pingback: Das CSS-Klappmen
  32. Hi.

    Klasse Sache das Teil. Funktioniert im Firefox auch super. Habe aber ein anderes Problem:
    Die Navigation ist eingebettet in ein Frameset. Leider erscheint das aufklappmenü hinter/unter dem angrenzenden Frame. Hat jemand ne Ahnung wie das verhindert werden kann?
    Danke

  33. Hi Leute super sache das menü.

    nur will ich noch einebene hinzufügen.

    Bekomme es aber nicht hin.

    div#menu ul ul ul, div#menu ul ul li:hover ul ul {display: none;}

    div#menu ul ul li:hover ul, div#menu ul ul ul li:hover ul {display: block;}
    was muss ich da noch hinzufügen.

  34. Das funktioniert wirklich schon sehr gut, dachte ich… Bis jemand die Seite im IE 7 geöffnet hat. Hier verschwinden die Untermenüs sobald man mit der Maus auf die zweite Ebene gehen will. Habe auch schon die csshover3.htc ausprobiert, bringt aber nix. Hat jemand eine Idee?

  35. Hallo,

    super sache, funktioniert bis dahin alles super, danke. gibt es noch ein paar möglichkeiten das css weiter auszuschmücken, würde gerne vorgefertigte button nehmen die auch einen rollover effekt haben sollten, also auch noch vorgefertigte buttons tauschen.
    ich vermute das das grundsätzlich kein problem darstellt, aber wenn ich in jeder zeile einen anderen button verwenden möchte gehen die probleme los, oder? Es würde aber erstmal reichen wenn ich zwei buttons, die sich bei mausberührung tauschen verwenden könnte auf denen dann der text liegt.

    danke nilix

  36. leider bin ich totaler anfänger und habe nix verstanden. wäre schön wenn du es einmal postest damit wir sehen können wie es aussieht , wenn es fertig ist!!!

  37. Irgendwie klappt da was nicht. Wenn ich das Beispiel im IE 8.x aufrufe, dann klappt es ohne Probleme. Wenn ich meinen eigenen Quelltext mit Verweis auf csshover.htc in der Voransicht anschauen will, funktionieren die Unterlinks nicht. In Firefox funktioniert es aber einwandfrei. Was stimmt da nicht ? Irgendwie greift er nicht auf das htc file zu so wie im Beispiel. Hat jemand eine Idee warum ?

    Gruss

    Aaron

  38. Sowas habe ich schon lange gesucht.
    Ein schlichtes, einfach verständliches code-Grundgerüst.
    Damit kann man echt schicke Navileisten zaubern.

    Vielen Dank!!!!!!!!!!!
    habt mir echt weitergeholfen

  39. Wie krieg ich das hin, dass Titel 1, Titel 2 usw auch einen Link bekommen?
    Wenn ich da einfach hinzufüge, wird das komisch dargestellt, weil das im Stylesheet ja so angegeben wurde.
    Hab ein bisschen rumexperimentiert, bin aber noch zu keinem Ergebnis gekommen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.