Funktionale CSS-Tabs Überarbeitet

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Die Idee von "CSS-Tabs" gibt es schon lange. Wenn man danach googelt, findet man viel über *gestaltete* CSS-Tabs, aber weniger über die Erstellung eines tatsächlich funktionalen Tab-Bereichs. Zumindest funktional, wie wir uns Tab-Bereiche heute vorstellen: einen Tab anklicken, einen neuen Inhaltsbereich sehen, ohne dass die Seite neu geladen wird.

Die Bewältigung funktionaler CSS-Tabs hat keine so tiefe Geschichte. Brad Kemper hat 2008 damit herumgespielt und versucht, den Pseudo-Selektor :checked mit Radiobuttons und Nachbar-Geschwister-Kombinatoren zu nutzen. Dies ist eine wirklich coole Technik, die man für Dinge wie erweiterbare/kollabierbare Baummenüs oder visuelle Ersetzung von Formularfeldern durch Grafiken (pionierhaft von Ryan Seddon) verwenden kann.

Ich persönlich habe vor einiger Zeit versucht, mit funktionalen Tabs herumzuspielen und bin auf sieben verschiedene Wege gestoßen, dies zu tun. Die meisten konzentrierten sich auf die Verwendung der :target Pseudo-Klasse und die meisten dieser Techniken waren schlecht. Eine war okay. Alle hatten einen Hauptfehler: Es mussten URL-Hashes verwendet werden, was die Seite zum Element mit der passenden ID "springen" ließ, was völlig unerwartet, ruckartig und insgesamt eine schlechte Erfahrung war.

Die Arbeit mit der Radio-Button/:checked-Technik ist viel besser, aber es gab einen langjährigen WebKit-Bug, der verhinderte, dass Pseudo-Klassen-Selektoren und Nachbar-Geschwister-Kombinatoren zusammenarbeiteten. Gute Nachrichten! Das ist seit stabilen Browser-Versionen Safari 5.1 und Chrome 13 behoben.

Also, machen wir das Ding auf die :checked-Weise, was meiner Meinung nach für jetzt und die nächsten Jahre der sauberste Weg ist.

Ist das eine Tabby-Katze? Verstehst du? (Wortspiel mit "tabby" und "tab")

HTML-Struktur

Ein Wrapper für die gesamte Gruppe, dann ist jeder Tab eine Div, die den Radiobutton (für die Funktionalität), ein Label (den Tab) und eine Inhalts-Div enthält.

<div class="tabs">
    
   <div class="tab">
       <input type="radio" id="tab-1" name="tab-group-1" checked>
       <label for="tab-1">Tab One</label>
       
       <div class="content">
           stuff
       </div> 
   </div>
    
   <div class="tab">
       <input type="radio" id="tab-2" name="tab-group-1">
       <label for="tab-2">Tab Two</label>
       
       <div class="content">
           stuff
       </div> 
   </div>
    
    <div class="tab">
       <input type="radio" id="tab-3" name="tab-group-1">
       <label for="tab-3">Tab Three</label>
     
       <div class="content">
           stuff
       </div> 
   </div>
    
</div>

CSS-Layout

Grundsätzlich

  1. Verstecke die Radiobuttons (wir müssen sie nicht sehen, sie müssen nur angeklickt oder nicht angeklickt sein).
  2. Float die Tabs, damit die Labels in einer Zeile von Links angeordnet werden.
  3. Positioniere die Inhaltsbereiche absolut genau übereinander.
  4. Wenn ein Radiobutton :checked ist, lasse den benachbarten Inhaltsbereich mit z-index darüber liegen (visuell sichtbar und die anderen versteckt).
.tabs {
  position: relative;   
  min-height: 200px; /* This part sucks */
  clear: both;
  margin: 25px 0;
}
.tab {
  float: left;
}
.tab label {
  background: #eee; 
  padding: 10px; 
  border: 1px solid #ccc; 
  margin-left: -1px; 
  position: relative;
  left: 1px; 
}
.tab [type=radio] {
  display: none;   
}
.content {
  position: absolute;
  top: 28px;
  left: 0;
  background: white;
  right: 0;
  bottom: 0;
  padding: 20px;
  border: 1px solid #ccc; 
}
[type=radio]:checked ~ label {
  background: white;
  border-bottom: 1px solid white;
  z-index: 2;
}
[type=radio]:checked ~ label ~ .content {
  z-index: 1;
}

Das ist ziemlich schlankes CSS und es lässt sich beliebig auf eine beliebige Anzahl von Tabs erweitern, indem man einfach mehr "Tab"-Divs im HTML hinzufügt.

JavaScript

Gibt es nicht, Käpten!

Warum dieser Weg genial ist

  • Er verwendet kein :target, also keine Seiten-Sprünge-Mist und keine Hijacking der Zurück-Taste.
  • Er ist barrierefrei. Die seltsamen Radiobuttons sind mit display: none versteckt, damit Screenreader sie nicht sehen und (vermutlich) verwirrt werden, und kein tatsächlicher Inhalt ist mit display: none versteckt;
  • Er funktioniert in Safari 5.1+, Chrome 13+, Firefox 3.6+, Opera 10+ und IE 9+. Vielleicht etwas tiefer bei Chrome, Firefox und Opera, aber Safari und IE sind definitiv korrekt.

Warum dieser Weg nicht genial ist

  • Er erfordert eine feste Höhe für den Tab-Bereich, was Mist ist. Ich glaube, es gibt vielleicht einen Weg, das zu beheben, auch wenn ich es noch nicht ganz geschafft habe.
  • Die Radiobutton-Sache ist etwas hackelig.
  • Er hat nicht die tiefste Browserunterstützung (IE 9 ist schon viel verlangt). Wenn man tiefere Unterstützung braucht, muss man JavaScript verwenden.

Verstanden, alles klar

Nur zum Spaß habe ich dem Live-Demo-Tab einige Übergänge hinzugefügt.

Sehen Sie den Pen
Funktionale CSS-Tabs
von Chris Coyier (@chriscoyier)
auf CodePen.

Die Geniale Theoretische Zukunft – display: stack;

Wie ich erwähnt habe, ist die Radiobutton-Sache ein wenig hackelig. Es ist toll, dass wir das jetzt machen können und die Erfahrung ist ziemlich gut, aber die Art und Weise, wie wir codieren müssen, ist weder elegant noch intuitiv. Tab Atkins, der CSS-Spezifikationen schreibt, denkt, dass display: stack; wahrscheinlich die Zukunft für eine Tabbed-Benutzeroberfläche über CSS ist.