„Off Canvas“ Muster sind unterschiedliche Ansätze für Layouts, bei denen Inhalte im Web nicht nur in einer vertikalen Spalte angeordnet sind. Zum Beispiel könnte die Navigation versteckt am linken Rand des „Canvas“ (des sichtbaren Browserfensters) positioniert und nach Bedarf eingeblendet werden. Anthony Colangelo hat jPanelMenu entwickelt, um genau das zu tun. Hakim El Hattabs Meny ist schicker, aber in seiner Funktion ähnlich.
Beide verwenden JavaScript. Ich dachte, es wäre lustig, zu versuchen, Anthony's jPanelMenu nur mit CSS nachzubilden. Das ist machbar – mit mehreren Vor- und Nachteilen.

Demo ansehen
Zwei Spalten, eine eingeklappt
Die hier verwendete Layout-Technik ist im Wesentlichen ein Zweispalten-Grid. Standardmäßig ist nur die linke Spalte 0% breit und die rechte Spalte 100% breit. Die linke Spalte ist die Navigation, die wir bei Bedarf einblenden wollen. Mit verstecktem Überlauf ist diese Spalte komplett verborgen.
<!-- I am collapsed by default -->
<nav id="main-navigation" class="navigation">
<a href="#">Nav Links</a>
<!-- more -->
</nav>
<!-- I am full width by default -->
<div class="page-wrap">
<header>
<a href="#main-navigation">Menu</a>
<h1>Title</h1>
</header>
<!-- content -->
</div>
.navigation {
/* Collapsed */
width: 0;
overflow: hidden;
position: fixed;
top: 0;
left: 0;
height: 100%;
}
.page-wrap {
width: 100%;
float: right;
}
Offener Menüzustand mit :target
Beachten Sie, dass dieser Link
<a href="#main-navigation">Menu</a>
Mit der ID von
<nav id="main-navigation" class="navigation">
Das ist ein ganz normaler Hash-Link. Die Seite wird zu diesem Element "springen". Wichtiger für uns ist, dass dieser Selektor übereinstimmt
#main-navigation:target {
}
Wenn dieser Link angeklickt wird, können wir das Menü einblenden, indem wir seine Breite erhöhen. Machen wir es am besten schön schiebend.
.navigation {
transition: width 0.3s ease;
}
#main-nav:target {
width: 20%;
}
Wir könnten es dabei belassen, und das Menü würde den Inhalt überlappen (stellen Sie sicher, dass es einen höheren z-index hat). Das wäre völlig in Ordnung. Aber wir haben Optionen. Wir könnten den Inhalt stattdessen nach rechts schieben. Das ist es, was zum Beispiel Facebook in seiner mobilen App tut, wenn das linke Menü geöffnet wird. Oder wir könnten den Hauptinhalt zusammenschieben und ein 20%/80% Grid erstellen. Das werden wir hier tun.
Aber warten Sie... wie wählen wir die .page-wrap nur in dem spezifischen Zustand aus, wenn das Menü geöffnet ist? Wir können einen benachbarten Geschwisterselektor verwenden!
#main-nav:target + .page-wrap {
width: 80%;
}
So einfach ist das.
Um das Menü zu schließen, müssen wir nur den Hash-Link in der URL entfernen. Geben Sie im Wesentlichen einen Link wie diesen irgendwo ein
<a href="#">Close Menu</a>
Wenn Sie es wirklich schick machen wollen, könnten Sie verschiedene Links verstecken/anzeigen, die sich an exakt derselben Stelle befinden, um einen "Toggle-Link" zu erstellen.
Vorteile
Alles CSS! Weniger Code insgesamt. Weniger zu ladende Ressourcen. Funktioniert ohne JavaScript. Sanftere Übergänge als JavaScript-Übergänge.
Nachteile
Begrenzte Browserunterstützung. :target ist ab IE9+ (das Ganze schlägt fehl, wenn :target nicht funktioniert). Übergänge sind ab IE 10+. Das Ändern von Klassen oder das Ein-/Ausblenden/Animieren mit JavaScript kann Browserbeschränkungen umgehen. Außerdem haben Sie mehr Freiheit bei der Anordnung des Markup, anstatt gezwungen zu sein, die spezifische Reihenfolge einzuhalten, die hier präsentiert wird. Möglicherweise auch etwas bessere Semantik, da keine separaten Links zum Öffnen und Schließen des Menüs benötigt werden.
Genial, einige iPad-Apps haben so etwas. Wie Twitter, die iPad-App von Facebook hat diese Art von anfänglich versteckter Navigation hinter dem Hauptlayout.
Danke.
Könntest du etwas Ähnliches (ohne zusätzlichen Markup) mit einem Label, einer versteckten Checkbox und dem :checked-Selektor machen? Die Selektoren wären wahrscheinlich etwas komplexer, aber es sollte möglich sein.
Es stellt sich heraus, ja, das kannst du! Das ist ein etwas saubererer Markup im Header selbst, mit dem Nachteil, dass die Checkbox hinzugefügt werden muss. Es gibt den zusätzlichen Vorteil, dass man nicht mit dem Browserverlauf herumhantiert.
http://codepen.io/jetpacmonkey/pen/ktIJz
Yep. Das nennt sich der Checkbox-Hack. Tatsächlich zeigt Chris dir hier einige Dinge, die du damit machen kannst: https://css-tricks.de/the-checkbox-hack. Ich würde hinzufügen, dass die Verwendung einer Checkbox die Abwärtskompatibilität mit jQuery etwas erleichtern könnte, da du Bedingungen schreiben könntest, je nachdem, ob die Box :checked ist oder nicht.
Was wirklich schön wäre, wäre Tab Atkins' Idee für den Toggle-Zustand: http://www.xanthir.com/b4Kn0
Tolle Idee! Ein möglicher Nachteil im Vergleich zu :target ist, dass die Auswahl eines Menüpunkts das Menü nicht einklappt, was bedeutet, dass der Benutzer erneut auf das Label klicken muss, um es zu schließen, oder Sie müssen JavaScript verwenden, um die Box zu de-selektieren. Dies hängt jedoch alles von Ihrer spezifischen Implementierung ab, ob ein automatisches Schließen notwendig ist.
Coole Demo! Ein weiterer Nachteil ist, dass diese Methode den Browserverlauf beeinflusst. Das könnte mit der History API behoben werden, aber die Idee ist ja, kein JavaScript zu verwenden.
Absolut einverstanden. Das ist ein schönes Konzept, aber in der Anwendung unpraktisch. Außerdem würde eine reine Breitenreduzierung Probleme mit verschachtelten Bildern und Layout verursachen, was es seltsam aussehen ließe. Ich glaube immer noch, dass JS die beste Lösung für diese Methode ist.
Sehr cool, aber mein größtes Argument gegen diese Methode ist, dass durch die Verwendung von :target bei jedem Öffnen und Schließen des Menüs ein neuer Verlaufseintrag hinzugefügt wird, was wiederum bedeutet, dass die Zurück-Taste völlig verhunzt wird.
Das ist auch immer ein Problem für mich. Glücklicherweise hat Jeremy eine weitere Version gemacht, die dieses Problem nicht hat: http://codepen.io/jetpacmonkey/pen/ktIJz
Ich LIEBE das! Ich liebe auch Anthonys Plugin.
Ich habe es gerade mit einigen hinzugefügten Media Queries ausprobiert, um die Navigationsanzeige ein-/auszublenden: http://codepen.io/Jenn/pen/tIFaH
Schöne Demo, aber ich bevorzuge die :checked-Lösung wegen des Verlaufsproblems (ja, Telefone haben Zurück-Buttons und die werden benutzt...) und sei vorsichtig mit der Unterstützung auf Mobilgeräten (mit beiden Techniken).
Seien Sie vorsichtig mit jPanelMenu, es funktioniert nicht mit einigen Browsern... (Android 2.1 zum Beispiel).
Problem mit der Navigation und der Benutzer ist weg... immer mit "schlechten" Browsern testen!
Wenn ich das mit CSS angefangen hätte, hätte ich eine Checkbox verwendet, die beim Aktivieren das Menü anzeigt. Dann hätte ich den :checked-Selektor und den + Selektor verwendet.
Das entfernt den hässlichen Hash in der URL, aber ist die Browserunterstützung besser?
Schöne kleine Demo Chris!
Ich persönlich finde diese Navigationsimplementierung wirklich gut, aber eine Sache, die man bedenken sollte, ist die Benutzerfreundlichkeit des Menüs im Querformat auf einem Smartphone. Wenn du viele Links in der Navigation hast, sind sie unerreichbar, da das Navigationspanel feststeht (nicht scrollt).
http://cl.ly/Kjwy
Vielleicht könnte das Hinzufügen von `overflow:scroll` im geöffneten Zustand eine Lösung sein...
Vielen Dank fürs Teilen. Das ist wirklich cool.
Ich werde es testen :-)
Ich mag dieses Konzept, aber das Drei-Linien-Menüsymbol wirkt auf mich unnatürlich, wenn sich das Menü von links statt von oben hereinzieht. Dieses Symbol lässt mich es greifen und nach unten ziehen wollen. Ideen für ein besseres Symbol?
Schöne Demo. Ich habe das in einigen Projekten ausprobiert. Ich habe auch festgestellt, dass es sich gut eignet, um geteilte Abschnitte ohne JS zu erstellen. Wie du sagst, schlägt es jedoch in älteren Browsern fehl.
<a href=”#”> zum Schließen des Menüs hat den Nachteil, dass man zum Seitenanfang springt, anstatt an der Stelle zu bleiben, wo man vor dem Öffnen des Menüs war.
Das wäre nur bei einem Menü der Fall, das mitscrollt, d.h. `position: fixed;`, aber meistens verursacht das auf Mobilgeräten eine große Verzögerung. Daher ist der Benutzer in den meisten Fällen bereits am oberen Rand der Seite. Wenn Sie dies immer noch verhindern möchten, können Sie – mit jQuery – die Standardaktion stoppen.
Nett. Hier ist ein Off-Canvas-Beispiel mit dem allgemeinen Geschwisterselektor.
http://www.vinceallen.com/offcanvas/index.html
Noch wichtiger, Mr. Coyer! Wie hast du dieses „☰“-Zeichen bekommen! Teile es mit der Klasse!
Unicode 9776 -> ☰
Das ist ein guter! Danke, Jeremy!
Ich denke, das wäre am nützlichsten für die Verwendung auf Mobilgeräten. Da es keine mobilen Geräte gibt, auf denen IE8 und älter laufen, ist die eingeschränkte Browserunterstützung überhaupt ein Problem?
Wie immer, toller Beitrag! Danke!
Gute Leistung, das ohne JS zum Laufen zu bringen! Ich hätte jedoch absolute/relative Positionierung und das Einblenden meiner Seitenleiste (während das Hauptpanel ausgeblendet wird) bevorzugt, damit kein Textumbruch stattfindet (was die Leistung auf einer komplexen Seite beeinträchtigen kann).
Ich habe vor ein paar Wochen etwas Ähnliches gemacht. Aber robuster mit jQuery.
Schauen Sie es sich an (Login mit: D4DD)
Ich mag es, weil man keine fehlerhaften horizontalen Scrollbalken bekommt... aber der Zurück-Button ist wegen der Klicks auf den Button / Link zum Öffnen und Schließen des Menüs total... ups?
Gut zu sehen, dass es ohne JS funktioniert. Mehr Menüpunkte benötigen `overflow: scroll`.
Hallo, sollte in der ersten Box die ID des Nav-Elements nicht „main-nav“ statt „main-navigation“ sein?
Nein, das gesamte CSS etc. basiert auf „main-navigation“, obwohl du es jederzeit anders nennen kannst – zum Beispiel „main-nav“ –, solange du in deinem CSS und den Link- hrefs konsistent bleibst.
Natürlich... es ist die Konsistenz, von der ich spreche.
Chris nannte #main-navigation im HTML, dann #main-nav im CSS...
Ich dachte, ich hätte das sogar überprüft, um sicherzugehen, aber du hast zu 100 % Recht.
Genial, danke fürs Teilen! Ich habe dies als Grundlage genommen und eine Version implementiert, bei der der Text nicht gequetscht wird, sondern zur Seite geschoben wird (Facebook-ähnlich) sowie einige nette Übergänge für die Inhaltsbox.
http://pixels-paper.nl/labs/nav/index.html
Hast du noch das Beispiel, bei dem der Text nicht gequetscht, sondern beiseite geschoben wird?
Beste Grüße
Hallo Jelmer... dieselbe Frage wie Laszlo: Kannst du helfen, das page-wrap um denselben Betrag wie die Breite von main-nav beiseite zu schieben?
Wenn du einen schönen Effekt des seitlichen Schiebens der gesamten Seite erzielen möchtest, kannst du CSS-Transformationen verwenden, zum Beispiel diese Stile auf den Seiten-Wrapper anwenden.
Danke für das Menü, das nur mit CSS funktioniert. Ich habe eine Frage: Wenn das Menü geöffnet ist, möchte ich alle Klick-Events im page-wrap-Container deaktivieren, um zu verhindern, dass der Benutzer auf Links im page-wrap klickt, oder ich möchte das Menü schließen, wenn der Benutzer auf page-wrap klickt. Ist das möglich?
Hallo,
Konntest du das Menü schließen?
Beste Grüße
Habe es gerade im Mobilformat angepasst, das Menü war nicht richtig für die Breite, also habe ich herausgefunden, wie man die Breite des Menüs für Mobilgeräte auf 75% ändert, wenn es im Mobil- oder Tablet-Ansicht ist http://codepen.io/riwakawebsitedesigns/pen/xHrIo
Link entfernt, werde bald eine neue Version machen und den neuen Link hier auf dieser Seite posten.
Tolle Arbeit Chris,
Gibt es eine Möglichkeit, dass .page-wrap die Breite (100% – Breite von #main-nav) hat?
Ich möchte nicht, dass mein #main-nav auf breiten Bildschirmen volle 20% einnimmt, also habe ich #main-nav:target so gestylt:
#main-nav:target{width: 20%;
max-width: 180px;
min-width: 130px;
}
Jede Anleitung wäre willkommen :-)
Hallo Chris und Co. Ich habe mich gefragt, ob mir hier (oder du Chris) bei einem Flyout-Menü-iOS7-Problem helfen könnte.
Ich halte mich für fortgeschritten in CSS, aber ich kann das einfach nicht lösen. Ich würde mich über jeden Tipp zu der oben genannten SO-Frage freuen!
Genial, danke fürs Teilen!