5202

ein Blog über technische Fragen zu Blogger

Dropout-Menü ohne Javascript

von
Stay foolish! Dropdown Menüs kann inzwischen jeder und hat inzwischen jeder - ist irgendwie kein wirklicher Hingucker mehr.

Deswegen heute eine neue Variation zum unendlichen Thema ein-Menü-mit-vielen-Unterpunkten und zwar als Dropout. Schaut euch die Demo an, das Dropout fährt per Klick aus!

Skizze!

Das Menü funktioniert in allen richtigen Browsern, im Internet Explorer ab 8+. Wer seinen Blog also für den Netscape Explorer optimieren will, für den ist das nichts :=).

Außerdem-ist-das-eine-Skizze, kein Tutorial! So was kann man nicht per copy/past in fünf Minuten in seinen Blog einbauen ... lest euch zumindest vorher durch, was ich dazu zu sagen habe, okay?

HTML

Das Menü ist zunächst einmal sehr simpel aufgebaut und zwar aus input Elementen mit dem Attribut radio:
<input id="box1" name="nav" type="radio" />      
<input id="box2" name="nav" type="radio" />      
<input id="box3" name="nav" type="radio" />     
<input id="box4" name="nav" type="radio" />      
<input id="box5" name="nav" type="radio" />  
Das radio Attribut meint, das nur jeweils ein input Element aktiv sein kann. Das wird später zum Schalter, mit dem wir das Dropout aus.- und einfahren.

Jedem input Element wird ein Label zugeordnet - in den Labels liegt ein <span> Container mit der 'Beschriftung'.
<ul id="nav_level_1">
 <li>
  <label for="box1">
   <span class="titel">green</span>
  </label>
 </li>
 <li>
  <label for="box2">
   <span class="titel">red</span>
  </label>
 </li>
 <li>
  <label for="box3">
   <span class="titel">yellow</span>
  </label>
 </li>
 <li>
  <label for="box4">
   <span class="titel">blue</span>
  </label>
 </li>
 <li>
  <label for="box5">
   <span class="titel">x</span>
  </label>
 </li>
</ul>
Unterhalb der input kommen die Links der zweiten Ebene in Listenform - alles zusammen schaut nun so aus:
<input id="box1" name="nav" type="radio" />      
<input id="box2" name="nav" type="radio" />      
<input id="box3" name="nav" type="radio" />     
<input id="box4" name="nav" type="radio" />      
<input id="box5" name="nav" type="radio" />    
<div class="holder">
<ul id="nav_level_21">
 <li><a href="">willow</a>
  </li>
 <li><a href="">frog</a>
  </li>
 <li><a href="">grass</a>
  </li>
     <li><a href="">leaf</a>
  </li>
</ul>
<ul id="nav_level_22">
 <li><a href="">fire</a>
  </li>
 <li><a href="">love</a>
  </li>
 <li><a href="">heat</a>
  </li>
 <li><a href="">rose</a>
  </li>
</ul>
<ul id="nav_level_23">
 <li><a href="">sun</a>
  </li>
 <li><a href="">note</a>
  </li>
 <li><a href="">sky</a>
  </li>
 <li><a href="">bvb</a>
  </li>
</ul>
<ul id="nav_level_24">
 <li><a href="">wave</a>
  </li>
 <li><a href="">note</a>
  </li>
 <li><a href="">sky</a>
  </li>
 <li><a href="">ocean</a>
  </li>
</ul>
<ul id="nav_level_1">
 <li>
  <label for="box1">
   <span class="titel">green</span>
  </label>
 </li>
 <li>
  <label for="box2">
   <span class="titel">red</span>
  </label>
 </li>
 <li>
  <label for="box3">
   <span class="titel">yellow</span>
  </label>
 </li>
 <li>
  <label for="box4">
   <span class="titel">blue</span>
  </label>
 </li>
 <li>
  <label for="box5">
   <span class="titel">x</span>
  </label>
 </li>
</ul>
Lasst euch von den vielen Listen und Links nicht verwirren sondern versucht immer die Struktur dahinter zu sehen ... eine Liste beginnt mit einem <ul> Tag und endet mit einem </ul> Tag, dazwischen liegen <li> Tags und in denen liegen die Anker-Elemente mit den Links.

CSS

Wir fangen mit einem Reset an, ansonsten würden wir mit der Bloggereigene CSS später Probleme bekommen - die input Elemente blenden wir hier schon aus, zum 'schalten' brauchen wir sie nicht:
/*reset*/
.widget .post-body li, .widget .post-body ul, label, ul, li  { margin:0; padding: 0}
input {display: none}
Ebene 1
Die erste Ebene ist eine Linkliste. Um die einzelnen Links horizontal auf eine Ebene zu bringen, benützen wir die Eigenschaft display: inline-block - wir ersparen uns damit nerviges floaten und clearen:
#nav_level_1  li {
display: inline-block;
}
In den Listenpunkten liegen die Labels, d.h. die Schaltflächen. Geben wir ihnen a bisserl Style:
#nav_level_1  li label {
    font-size: 25px;
    display: inline-block;
    padding: 8px 0 8px 20px;
    margin: 0;
    background: #98B924;
    text-align: center;
    width: 105px;
    min-width: 105px;
    color: #fff;
    -webkit-border-radius: 10px 0 10px 0;
       -moz-border-radius: 10px 0 10px 0;
            border-radius: 10px 0  10px 0;
    -webkit-transition: all .3s;
       -moz-transition: all .3s;
        -ms-transition: all .3s;
         -o-transition: all .3s;
            transition: all .3s;
}

Die Eigenschaft min-width ist ein kleiner Hack für Chrome für die Transition - langsam kommt das wir-müssen-Hacks-schreiben wieder richtig in Mode :=).

Der Hover dazu:
#nav_level_1  li label:hover {
color: #fff;
 background: #b8da40;
  -webkit-transition:  .1s all .1s;
      -moz-transition: .1s all .1s;
       -ms-transition: .1s all .1s;
        -o-transition: .1s all .1s;
           transition: .1s all .1s;

}
Die Schreibweise .1s all .1s ist eine Kurzschreibweise und gibt eine Verzögerungswert von .1s bei der Transition - dadurch wird die Transition ruhiger und ohne 'flackern'.

Wir personalisieren die einzelnen Labels mit der super-coolen Eigenschaft nth-of-type(n)
#nav_level_1  li:nth-of-type(2) label {
background: #bf3030
}
#nav_level_1  li:nth-of-type(2) label:hover {
background:#ff0000
}
#nav_level_1  li:nth-of-type(3) label {
background: #eec13c
}
#nav_level_1  li:nth-of-type(3) label:hover {
background:#fff573
}
#nav_level_1  li:nth-of-type(4) label {
background: #06668b
}
#nav_level_1  li:nth-of-type(4) label:hover {
background:#379ce5
}
Weil die Eigenschaft nth-of-type(n) super cool ist, versteht sie logischerweise der Internet Explorer nicht - wer ein Herz für Internet-Explorer-Benutzer hat, kann das auch mit id's schreiben ... ist mir persönlich zu doof, es geht ja funktionell nichts verloren.

Das fünfte und letzte Label ist anders als die anderen - das wird der 'Knopf' zum einklappen:
#nav_level_1  li:nth-of-type(5) label {
  color: #111;
  margin-left: 20px;
  min-width: 30px;
  width: 20px;
  background: #fff;
  padding: 0 ;
}
#nav_level_1  li:nth-of-type(5) label:hover {
  background: red
}
Ebene 2
Die Ebene 2 liegt in einem <div> Container mit der Klasse .holder. Wir wollen innerhalb dieses Containers die Ebene 2 verschieben und vor allem am Anfang vor den Besuchern verstecken.

Damit das funktioniert, braucht der Container .holder mindestens eine relative Positionierung und ein overflow: hidden.
.holder {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: 0;
  margin: 5px 0 0 0;
  display: block;
  -webkit-transition:  all .3s;
      -moz-transition: all .3s;
       -ms-transition: all .3s;
        -o-transition: all .3s;
           transition: all .3s;
}
Wichtig: Mit der Höhe height: 0 ist der Container am Anfang 'geschlossen'.
Link-Liste
Die Link-Liste der Ebene 2 wird analog zur Ebene 1 gebaut, mit einem Unterschied - wir geben im Hover den Ankerelementen eine Breite width: 200px - womit der coole Hovereffekt für die Ebene 2 entsteht.

Damit die Ebene 2"smooth" reagiert, geben wir in der Transition wieder eine Verzögerung von .1s - das verhindert 'Sprünge'.
/* Link_Liste Holder */

.holder li{
display: inline-block
}
.holder li a  {
 text-decoration: none;
 display: inline-block;
 padding: 8px 0 8px 20px;
 font-size: 19px;
 margin: 0;
 background: #98B924;
 text-align: center;
 width: 105px;
 border: 2px solid;
 border-colour: transparent;
  color: #fff;
   -webkit-border-radius: 10px 0 10px 0;
      -moz-border-radius: 10px 0 10px 0;
          border-radius: 10px 0  10px 0;
   -webkit-transition:  all .3s;
       -moz-transition: all .3s;
        -ms-transition: all .3s;
         -o-transition: all .3s;
            transition: all .3s;
}
.holder li a:hover {
 width: 200px;
 -webkit-transition:  .5s all .1s;
     -moz-transition: .5s all .1s;
      -ms-transition: .5s all .1s;
       -o-transition: .5s all .1s;
          transition: .5s all .1s;
}
#nav_level_21 li a:hover {
 background: #b8da40;
}
#nav_level_22 li a {
background: #bf3030
}
#nav_level_22 li a:hover {
background:#ff0000;
}
#nav_level_23 li a {
background: #eec13c
}
#nav_level_23 li a:hover {
background:#fff573;
}
#nav_level_24 li a {
background: #06668b;
}
#nav_level_24 li a:hover {
background:#379ce5;
}

Bring them out!

Bis jetzt waren das alles nur Styleanweisungen, keine Funktion - freut euch, die kommen jetzt :=).

Wir benutzen dazu den General Sibling Combinator, der uns erlaubt, eine CSS-Eigenschaft auf jedes Objekt anzuwenden, das einem bestimmenten HTML-Element folgt!.

Der General Sibling Combinator wird mit ~ [Tilde] geschrieben. Man könnte eigene Posts über diesen Combinator schreiben ...
Holder 'öffnen'
Erster Schritt: Wir öffnen den 'Holder' Container:
input:checked ~ .holder {
   height:46px; 
   -webkit-transition:  all .3s;
       -moz-transition: all .5s;
        -ms-transition: all .5s;
         -o-transition: all .5s;
            transition: all .5s;}
Layer verstecken
Zweiter Schritt: Die einzelnen Layer der Ebene 2 werden absolute positioniert und mit margin-left um 600px nach links (außerhalb des Blickfeldes) verlagert:
.widget .holder ul{
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  margin-left: -600px;
   -webkit-transition:  all .5s;
       -moz-transition: all .5s;
        -ms-transition: all .5s;
         -o-transition: all .5s;
            transition: all .5s;
}
Layer einblenden
Dritter Schritt: Per Klick auf ein Label werde die Layers mit margin-left punktgenau eingeblendet:
#box1:checked ~ .holder ul#nav_level_21 {margin-left: 5px}
#box2:checked ~ .holder ul#nav_level_22 {margin-left: 118px}
#box3:checked ~ .holder ul#nav_level_23 {margin-left: 234px}
#box4:checked ~ .holder ul#nav_level_24 {margin-left: 352px}
Holder schließen
Letzter Schritt - mit dem kleinen 'x' schließen wir den Holder wieder:
#box5:checked ~ .holder {height: 0}

Zusammenfassung

Die gesamte CSS am Stück:
/*reset*/
.widget .post-body li, .widget .post-body ul, label, ul, li  { margin:0; padding: 0}
input {display: none}

/*Ebene 1*/
#nav_level_1 {
 list-style: none;
 padding:5px 0 0 5px;
 margin: 0
}
#nav_level_1  li {
 display: inline-block;
}
#nav_level_1  li label{
 font-size: 25px;
 display: inline-block;
 padding: 8px 0 8px 20px;
 margin: 0;
 background: #98B924;
 text-align: center;
 width: 105px;
 min-width: 105px;
  border: px solid;
  border-colour: transparent;
   color: #fff;
  -webkit-border-radius: 10px 0 10px 0;
        -moz-border-radius: 10px 0 10px 0;
            border-radius: 10px 0  10px 0;
    -webkit-transition:  all .3s;
        -moz-transition: all .3s;
         -ms-transition: all .3s;
          -o-transition: all .3s;
             transition: all .3s;
}
#nav_level_1  li:nth-of-type(2) label {
 background: #bf3030
}
#nav_level_1  li:nth-of-type(2) label:hover {
 background:#ff0000
}
#nav_level_1  li:nth-of-type(3) label {
 background: #eec13c
}
#nav_level_1  li:nth-of-type(3) label:hover {
 background:#fff573
}
#nav_level_1  li:nth-of-type(4) label {
 background: #06668b
}
#nav_level_1  li:nth-of-type(4) label:hover {
 background:#379ce5
}
#nav_level_1  li:nth-of-type(5) label {
 color: #111;
 margin-left: 20px;
 min-width: 30px;
 width: 20px;
 background: #fff;
 padding: 0 ;
}
#nav_level_1  li:nth-of-type(5) label:hover {
background: red
}
#nav_level_1  li label:hover {
color: #fff;
 background: #b8da40;
  -webkit-transition:  .1s all .1s;
      -moz-transition: .1s all .1s;
       -ms-transition: .1s all .1s;
        -o-transition: .1s all .1s;
           transition: .1s all .1s;
}
/* Ebene 2 */
.holder {
 position: relative;
 overflow: hidden;
 width: 100%;
 height: 0;
 margin: 5px 0 0 0;
 display: block;
   -webkit-transition:  all .3s;
       -moz-transition: all .3s;
        -ms-transition: all .3s;
         -o-transition: all .3s;
            transition: all .3s;
}
.holder li{
display: inline-block
}
.holder li a  {
 text-decoration: none;
 display: inline-block;
 padding: 8px 0 8px 20px;
 font-size: 19px;
 margin: 0;
 background: #98B924;
 text-align: center;
 width: 105px;
    border: 2px solid;
  border-colour: transparent;
  color: #fff;
    -webkit-border-radius: 10px 0 10px 0;
       -moz-border-radius: 10px 0 10px 0;
            border-radius: 10px 0 10px 0;
   -webkit-transition:  all .3s;
       -moz-transition: all .3s;
        -ms-transition: all .3s;
         -o-transition: all .3s;
            transition: all .3s;
}
.holder li a:hover {
 -webkit-transition:  .5s all .1s;
     -moz-transition: .5s all .1s;
      -ms-transition: .5s all .1s;
       -o-transition: .5s all .1s;
           transition:.5s all .1s;
}
#nav_level_21 li a:hover {
 color: #fff;
  background: #b8da40;
}
#nav_level_22 li a {
 background: #bf3030
}
#nav_level_22 li a:hover {
background:#ff0000;
}
#nav_level_23 li a {
background: #eec13c
}
#nav_level_23 li a:hover {
background:#fff573;
}
#nav_level_24 li a {
background: #06668b;
}
#nav_level_24 li a:hover {
background:#379ce5;
}

/* bring them out */
.widget .holder ul{
 height: 30px;
 position: absolute;
 top: 0;
 left: 0;
 z-index: 1;
 margin-left: -600px;
   -webkit-transition:  all .5s;
       -moz-transition: all .5s;
        -ms-transition: all .5s;
         -o-transition: all .5s;
            transition: all .5s;
}
input:checked ~ .holder {
   height:46px; 
   -webkit-transition:  all .3s;
       -moz-transition: all .3s;
        -ms-transition: all .3s;
         -o-transition: all .3s;
            transition: all .3s;}
#box1:checked ~ .holder ul#nav_level_21 {margin-left: 5px}
#box2:checked ~ .holder ul#nav_level_22 {margin-left: 118px}
#box3:checked ~ .holder ul#nav_level_23 {margin-left: 234px}
#box4:checked ~ .holder ul#nav_level_24 {margin-left: 352px}
#box5:checked ~ .holder {height: 0}

Aufwand

Das nachzubauen ist weniger kompliziert als es ausschaut, trotzdem müsst ihr da richtig Zeit investieren, das ist nichts für so-mal-zwischendurch und per copy/past in den Blog

Ich beantworte gerne Fragen dazu, aber bauen müsst ihr's selber, das kann ich euch nicht abnehmen :=).

... ist aber auch gut so, nur durch's selber-machen lernt ihr was :=):

Fragen?

Fragen zu dieser Skizze gerne hier im Post - falls ihr Fragen habt, die thematisch nicht so reinpassen, dafür gibt's jetzt ein Forum.