Accordion, Slider, Tabs & Co. mit purem CSS Es muss nicht immer Javascript sein
In Zeiten von jQuery und unzähligen darauf basierenden Lösungen, die mit ein wenig Copy and Paste in die eigene Seite eingebaut sind, übersieht man mitunter die Möglichkeiten, die HTML und CSS von Hause aus mitbringen. In diesem Artikel wird exemplarisch eine Technik vorgestellt, die als Grundlage für die verschiedensten Arten von Slidern, Tabs, Accordions u.ä. dienen kann.
Die Idee
Egal ob Slider oder Tabs oder irgendwas anderes in die Richtung, letzten Endes geht es immer um die Steuerung der Sichtbarkeit/Position von Elementen über einen Mausklick (oder vergleichbare Aktionen). Ein klassischer Ansatz hierfür ist die Verwendung der Pseudoklasse :target
. Dieser funktioniert im Grunde auch prima, allerdings kommt man doch relativ schnell an die Grenzen der Komfortabilität. Wesentlich mehr Flexibilität bietet da der Weg über den Einsatz von input
-Elementen (Radiobuttons und/oder Checkboxes). Auf deren Status lässt sich mit der Pseudoklasse :checked
zugreifen, womit wir unsere Steuerlemente haben. Mehr braucht es für die Funktionalität nicht!
Der Mechanismus
Ein simpler HTML-Code könnte demnach wie folgt aussehen:
Alles was innerhalb des
div
-Elements steht wird im nächsten Schritt per css angesprochen.Das können beliebige Elemente sein - Überschriften, Absätze, Listen etc.
Um nun das dem input
folgende div
anzusprechen, können wir einen Nachbarselektor verwenden. Hier würde sowohl der direkte (F + E) als auch der indirekte (F ~ E) funktionieren, damit wir später etwas flexibler sind, nehme wir den indirekten und weisen einen Rahmen sowie ein wenig Innenabstand zu:
input ~ div { border: 1px solid #ddd; padding: .4em; }
Okay, zugegebenermaßen soweit nicht besonders spektakulär. Spaßig wird es aber, wenn wir noch eine Kleinigkeit ergänzen. Mit der Pseudoklasse :checked
für das Element input
bekommen wir eine Möglichkeit auf den Status dieses Elements zu reagieren. Ändern wir z.B. die Opazität bei aktivierter Checkbox:
input:checked ~ div { opacity: 0; }
Fallback
Die Pseudoklasse :checked
wird von jedem modernem Browser und dem IE ab Version 9 verstanden. In diesem einfachen Beispiel kein wirkliches Problem - in älteren Browsern wird halt nichts ausgeblendet.
Denken wir aber einen Schritt weiter, so kommen wir relativ schnell zu einem Szenario, dass wir aus einer Menge von Elementen immer nur eines einblenden möchte (z.B. bei einem klassischen Accordion). Es liegt also nahe, erstmal alle Elemente auszublenden und erst im nächsten Schritt das gewünschte Element gezielt wieder einzublenden, z.B. so:
input ~ div { opacity: 0; } input:checked ~ div { opacity: 1; }
Das Problem dabei ist, dass auch Browser, die Pseudoklasse :checked
nicht verstehen, die Inhalte prima ausblenden, nur das Einblenden schlägt bei diesen natürlich fehl … wir sehen, dass wir nichts sehen. Dieser Problematik können wir jedoch relativ leicht begegnen, indem wir sowohl das Ein- als auch das Ausblenden per Pseudoklasse regeln. Alles was wir dazu noch brauchen ist die Negationspseudoklasse :not(s)
. Klingt schlimmer als es ist, der CSS-Teil verändert sich nur marginal:
/* allgemeine Styles für alle Browser */ input ~ div { } /* Ausblenden, wird nur von modernen Browsern interpretiert */ input:not(:checked) ~ div { opacity: 0; } /* Einblenden, wird nur von modernen Browsern interpretiert */ input:checked ~ div { opacity: 1; }
Für den Fall, dass der Browser die Pseudoklassen nicht versteht, werden so auf jeden Fall alle Inhalte angezeigt. Sieht vielleicht nicht so hübsch aus wie geplant, aber es geht immerhin kein Inhalt verloren.
Da in der Praxis im Regelfall nur der IE in seinen alten Versionen vorkommt, reicht es zumeist, diesem mit ein wenig Javascript auf die Sprünge helfen. Eine relativ einfach zu integrierende Lösung ist selectivizr (http://selectivizr.com/).
Ein kleines Beispiel
Der oben aufgezeigte Mechanismus lässt sich natürlich in eine hübsche Verpackung hüllen. Zum einen durch Einführung von Elementen, mit denen wir den Status der Checkboxes steuern können - genau: das gute, alte label
. Zum anderen durch ein paar Zeilen CSS, mit denen die einzelnen Elemente aufgehübscht werden. Bauen wir als Beispiel eine simple Box, die wir bei Bedarf ein- und ausblenden können.
Im ersten Schritt ergänzen wir den HTML-Code um zwei label
-Elemente. Für die Steuerung würde natürlich auch eines ausreichen, aber um passend zum Status der Checkbox eine sinnvolle Beschriftung anzuzeigen, werden wir uns mit zweien leichter tun. Die ganze Box verpacken wir noch in ein div
-Element. Je nach Szenario kann hier natürlich auch jedes andere Element verwendet werden - wenn es also etwas semantisch passenderes gibt, nur zu.
Hier steht ein toller Inhalt, der beliebige Elemente enthalten kann:
- Listen
- Bilder
- …
Der Mechanismus ist identisch zum oben skizzierten, wird hier aber noch auf die Sichtbarkeit des passenden label
-Elements erweitert. Der Rest des Codes dient nur der Optik und kann natürlich komplett nach eigenen Bedürfnissen angepasst werden. Auch für die Funktionalität gibt es selbstverständlich einige Alternativen zur Opazität - einfach mal probieren.
.toggleBox { position: relative; border: 1px solid #ddd; } /* Ausblenden des input-Feldes */ .toggleBox input { position: absolute; left: -99999px; } /* Gestaltung der labels */ .toggleBox label { display: block; background: #68B022; color: #fff; padding: .4em; text-align: center; cursor: pointer; } .toggleBox label:hover { background: #ddd; } /* Der Aufklappmechanismus */ .toggleBox input:not(:checked) ~ div { opacity: 0; height: 0; } .toggleBox input:checked ~ div { opacity: 1; padding: .8em; -webkit-transition: opacity 1s ease-in-out; -moz-transition: opacity 1s ease-in-out; -ms-transition: opacity 1s ease-in-out; -o-transition: opacity 1s ease-in-out; transition: opacity 1s ease-in-out; } /* Steuerung der Sichtbarkeit der labels */ .toggleBox input:not(:checked) ~ .close, .toggleBox input:checked ~ .open { display: none; }
Fazit
Die Pseudoklasse :checked
ermöglicht es, an vielen Stellen auf den Einsatz von Javascript zu verzichten. An die Grenzen stößt man immer dann, wenn es an „richtige” Programmierung geht. Berechnungen, zeitgesteuertes ändern von Objekten und ähnliche Dinge sind nachwievor mit CSS nicht oder nur vergleichsweise umständlich lösbar (z.B. Keyframes Animation mit CSS3). Die Browserunterstützung ist relativ gut, was einen trotzdem nicht davon abhalten sollte einen sinnvollen Fallback einzubauen.
So sieht es aus
Hier steht ein toller Inhalt, der beliebige Elemente enthalten kann:
- Listen
- Bilder
- …
.toggleBox { position: relative; border: 1px solid #ddd; } /* Ausblenden des input-Feldes */ .toggleBox input { position: absolute; left: -99999px; } /* Gestaltung der labels */ .toggleBox label { display: block; background: #68B022; color: #fff; padding: .4em; text-align: center; cursor: pointer; } .toggleBox label:hover { background: #ddd; } /* Der Aufklappmechanismus */ .toggleBox input:not(:checked) ~ div { opacity: 0; height: 0; } .toggleBox input:checked ~ div { opacity: 1; padding: .8em; -webkit-transition: opacity 1s ease-in-out; -moz-transition: opacity 1s ease-in-out; -ms-transition: opacity 1s ease-in-out; -o-transition: opacity 1s ease-in-out; transition: opacity 1s ease-in-out; } /* Steuerung der Sichtbarkeit der labels */ .toggleBox input:not(:checked) ~ .close, .toggleBox input:checked ~ .open { display: none; }
Hier steht ein toller Inhalt, der beliebige Elemente enthalten kann:
- Listen
- Bilder
- …
Meine Meinung
Andere Meinung? Fragen? Ergänzungen? Hier ist der Platz dafür. Bitte beachte: Da hier jeder schreiben kann, werden zum Schutz vor Spam und grenzwertigen Inhalten alle Kommentare vor der Veröffentlichung von mir gegengelesen. Deine E-Mailadresse wird ausschließlich für eventuelle Rückfragen und ggf. eine Benachrichtigung bei neuen Antworten verwendet und keinesfalls an Dritte weitergegeben.
Kommentare (27)
Hey, ich kenne mich mit CSS so gut wie gar nicht aus. Zum Thema ein- und ausblenden, denke ich, wäre es naheliegender, wenn man beim Aufruf der Seite „aufklappen“ angezeigt bekäme, also der Inhalt nicht angezeigt werden würde und nur nach Bedarf aufgeklappt würde. Wie sähe das Beispiel dann aus?
Einfach das input-Element vorgabemäßig nicht checken, also
checked="checked"
rauslöschen.Eine interessante Variante eines Sliders. Ich versuche so eine "css-only-Variante" gerade in eine Joomla-Seite einzubauen (in ein Custom-Html Modul). Ich habe nur gerade keine Idee, wie/wo ich die CSS Datei hinterlegen kann.
Haben Sie einen Tipp, wie ich das umsetzen kann?
Vielen Dank im Voraus!
Daniel H.
Hallo nochmal, meine Frage hat sich geklärt. Es war einfach die Template CSS Datei, in die ich die CSS Anweisungen hineinkopieren musste.
Vielen Dank trotzdem für den tollen Slider!
Hi!
Wunderbare schlanke Umsetzung! Danke! Daumen hoch!
Gesucht, gefunden, umgebaut & eingebaut.
Jetzt hab ich nur ein Problem:
Habe nach dem Inhalt ein Formular eingebaut. Dieses lässt sich jetzt nur ausfüllen/abschicken wenn die toggleBox aufgeklappt ist. Das Formular ist also irgendwie mit dem input-Elemt das zur Steuerung zum Aufklappen genutzt wird, verbunden. :-(
Hast du nen Tipp?
PS: Eigentlich ist das Formular in dem ich hier poste der Beweis dass es ne Lösung gibt. Aber ich komm nicht dahinter was du hier anders machst :-)
Hallo, ein sehr eleganter script! Google kann es ohne probleme Crawlen. Habe aber folgendes Problem damit:
Wenn der Text aufgeklappt ist, ist der Footer Abstand mit dem Ende der Seite ok, also normal (vgl. http://heels-high.net/mail1.jpg
Wenn ich zuklappe gibt es einen Abstand zum Ende der Seite. So hoch wie eben der Text hoch ist (vgl. http://heels-high.net/mail2.jpg).
Ich habe wie beschrieben checked="checked" rausgelöscht…
Wie kann ich das ändern? Kann mir bitte jemand helfen, vielen Dank.
@Mike: Ohne den Code zu sehen schwierig. Hast Du ein Beispiel dazu?
@rifki: Meine Vermutung wäre, dass Du die Höhe im ausgeblendeten Zustand nicht auf Null gesetzt hast (vgl. Zeile 29 im CSS-Teil des Beispiels).
Hi,
erstmal vielen Dank für diese tolle Lösung :).
Darf ich den Code auf meiner eigenen Website verwenden oder gibt es dafür Bedingungen die ich beachten muss?
Mit freundlichem Gruß
Marcel
Alle Codeschnipsel, die ich hier auf der Seite veröffentliche, können gerne in eigenen Projekten verwendet werden - egal ob als Anregung für eigene Basteleien oder Eins-zu-Eins-Kopie. Bei der Weitergabe an Dritte gilt: bitte Quelle angeben und kein Geld damit verdienen.
Texte und Bilder bitte nur mit ausdrücklicher Genehmigung verwenden.
Hallo, wie kann ich es anstellen, dass ich mehr als eine Box habe und dann nur eine aufklappt und alle anderen zuklappen? Stehe gerade auf dem Schlauch.
Kommt drauf an, wie Dein HTML aufgebaut ist.
Wenn immer abwechselnd input und Box kommen, dann funktioniert es wie oben skizziert, nur mit dem Nachbarselektor (+) statt dem Geschwisterselektor. Im CSS steht also sowas wie:
input:checked + .box {
display: block;
}
Wenn der HTML-Teil so aufgebaut ist, dass es mit dem Nachbarselektor nicht weiterkommt, verwendet man entsprechende Klassen und/oder IDs. Sieht im CSS dann so aus:
#toggleBox1:checked ~ .box1,
#toggleBox2:ckecked ~ .box2 {
display: block;
}
Hallo zusammen,
Super Coding, weiter so… denoch habe ich ein Problem in der Einbindung Wordpress Template von Catchthemes.com. Im Beitrag wird nach dem zuklappen, also nach beenden der Div Box </div> der Code <br clear="all"> nicht angenommen, nach einmaligen Öffnen bleibt die Höhe des Inhaltes im Content stehen, nach dem Schliessen, also die Höhe als freier PLatz und dann kommt erst der Footer.
Beispiel: http://raum19.de/inside/interaktive_webseiten/
@rifki: Ich hatte das Problem mit dem Abstand nach dem Zuklappen auch und bei mir hat es geholfen ein overflow: hidden; für den ausgeblendeten Zustand (input:not(:checked) hinzuzufügen.
Hey,
habe gerade diesen Code gefunden, und bei mir zum Test in meine Demo Seite (Lokal) eingebaut.
Danke für den Code, das ist super schlank.
gruß M.
Hallo,
wie kann ich eine weitere Box hinzufügen? Wenn ich versuche eine Box hinzufügen, wird immer nur die erste geöffnet, egal welche ich anklicke.
Gruß
Jan
Hallo,
vielen Dank für den tollen Code. Gibt es eine Möglichkeit mehrere Boxen anzulegen, ohne jede neu bennen zu müssen? Wenn ich mehrere Boxen so einfüge, wird immer die erste geöffnet.
LG
Christine
@Christine und Jan:
Schlussendlich müsst Ihr immer für eine eindeutige Zuordnung von input-Element(en) zu Box(en) sorgen. Das kann über die HTML-Struktur und de passenden Selektor oder über die IDs, Klassen, Name o.ä. der Elemente laufen. Was besser passt, muss man im Einzelfall schauen.
Die Tabs oben (HTML, CSS, Resultat) sind ähnlich gelöst und vielleicht als Beispiel ganz hilfreich.
Sehr schöne, einfache und funktionale Lösung. Danke!
Ich hatte das Problem, das sich direkt nach dem letzten schließenden DIV stehender Text im Browser nicht mehr markieren und Links in dem Bereich sich nicht mehr anklicken ließen, dies jedoch nur in der Länge des aus zuklappenden Textes. Das Problem scheint nur aufzutreten, wenn die Checkbox ohne das Attribut checked verwendet wird, also anfänglich zugeklappt.
Bsp.:
aufklappen
zuklappen
Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore
et dolore magna aliquyam erat, sed diam voluptua. At vero
eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est
Lorem ipsum dolor sit amet.
Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore
et dolore magna aliquyam erat, sed diam voluptua.
Hier nicht markierbarer Text und nicht klickbarer Link. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
Lösung dafür: (hier height: 0; gegen display:none; tauschen)
.toggleBox input:not(:checked) ~ div {
opacity: 0;
/*height: 0;*/
display:none;
}
Ein toller Artikel. Könnte man das Auf- und Zuklappen statt ein-/ausblenden auch animieren?
Hallo,
echt gut das Aufklappen der Listen. Hat Spaß gemacht!
Ich habe es für meine Zwecke erweitert und zuerst in einer normalen html Datei gespeichert. Wenn ich diese in Browser aufmache, funktioniert es super. Aber wenn ich die entsprechenden Teile in die Beschreibung einer Kategorie in WordPress eingebe, dann ist die Box an sich zum Klicken da und der Inhalt der Boxen ist ganz zu sehen. Es sieht so aus, als wenn die CSS Anweisungen nicht richtig ausgeführt oder sogar ignoriert wird.
Wie kann man das Problem lösen? Ich will aber keine JavaScripts oder ähnliches verwenden.
VG
Ausprobierer
@Helmut: ja, alles was sich per transition ansprechen lässt, kann man hier nutzen.
@Ausprobierer: Da werden wohl durch Wordpress css-Anweisungen reinkommen, die für Kollisionen sorgen … da bleibt nur zu überprüfen, welche das sind.
Herzlichen Dank für den Artikel. Ich war auf der Suche nach einer CSS-Ausklappbox, die ich in einen WP-Shortcode verwandeln konnte. Funktioniert nach etwas Anpassung auch mit mehreren Shortcodes einwandfrei!
Hallo Herr Müller,
das ist ein ausgezeichneter Code für eine Auf- und Zuklappfunktion per css! Herzlichen Dank und funktioniert bei mir super.
Gibt es eine Möglichkeit auch per css, wenn die eine Box aufgeklappt wurde und ich die zweite aufklappe, dass dann die erste wieder geschlossen wird?
Über eine Antwort würde ich mich sehr freuen.
Beste Grüße
Dieter Glös
@Dieter Glös: Ja, einfach Radio-Buttons statt der Checkboxen nehmen.
Vielen Dank für diese kurze und effektive Script!
Fetten Daumen hoch
Sehr schöner code, hat auf anhieb funktioniert. Frage: Ist es möglich, gleichzeitig einen Scroll auszulösen? Ich möchte gern, dass sich nicht nur die Box nach unten öffnet, sondern gleichzeitig der gesamte Inhalt zu einem Anker nach oben springt, um die offene Box vollständig eingeblendet zu haben.