Ich habe kürzlich eine Präsentation von Ryan Seddon über Dinge, die man mit Checkboxen machen kann gesehen. Das brachte mich zum Nachdenken über einen ähnlichen Pseudoselektor, der auf der URL basiert, :target, und wie er zum Ein- und Ausblenden von Elementen für zusätzlichen Platz (insbesondere auf kleineren Bildschirmen) verwendet werden könnte. Ich stellte mir die Aufgabe, die iOS-Nachrichten-App ohne JavaScript nachzubilden, indem ich die großartigen CSS3-Selektoren und Übergänge voll ausnutze.
Einfaches Beispiel
Die folgenden Codebeispiele zeigen, wie wir eine Login-Box und Navigation ausblenden und bei Bedarf einblenden könnten.
<header id="hd">
<a href="/" class="logo">Company logo</a>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">News</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
<a href="#login">Log in</a>
<div id="login">
<fieldset>
<label for="username">Username:</label>
<input type="textbox" id="username">
<label for="password">Password:</label>
<input type="password" id="password">
<input type="submit" value="login"/>
<a href="/register">Sign up</a>
</fieldset>
</div>
</header>
<div id="bd">
<section>
<p>
... lorem ipsum content ...
</p>
</section>
<a href="#auxNav">Internal navigation</a>
<nav id="auxNav">
<ul>
<li><a href="#">First link</a></li>
<li><a href="#">Second link</a></li>
<li><a href="#">Another link</a></li>
</ul>
</nav>
</div>
body {
position: relative;
max-width: 960px;
margin: 0 auto;
}
#login {
position: absolute;
top: -200px;
right: 0;
-webkit-transition: top 0.3s ease-in-out;
-moz-transition: top 0.3s ease-in-out;
-ms-transition: top 0.3s ease-in-out;
-o-transition: top 0.3s ease-in-out;
transition: top 0.3s ease-in-out;
}
#bd {
position: relative;
overflow: hidden;
}
#auxNav {
position: relative;
overflow: hidden;
height: 60px;
}
#auxNav ul {
position: absolute;
left: -100%;
-webkit-transition: left 0.3s ease-in-out;
-moz-transition: left 0.3s ease-in-out;
-ms-transition: left 0.3s ease-in-out;
-o-transition: left 0.3s ease-in-out;
transition: left 0.3s ease-in-out;
}
/* The Magic Part */
#login:target {
top: 0;
}
#auxNav:target ul {
left: 0;
}
Indem wir die Navigation und den Login zuerst außerhalb des Bildschirms starten, können wir sie dann bei :target einblenden. Beachten Sie, wie der href-Attribut des Ankerlinks „#auxNav“ mit der ID des Navigationsmenüs „auxNav“ übereinstimmt.
Das auxNav zeigt, dass wir nicht die ID selbst ausblenden müssen, sondern beliebige Nachfahren davon ausblenden können.
Die „App“
Jede Nachricht („Bildschirm“) hat eine ID und ist außerhalb des Bildschirms positioniert. Wenn der Ankerlink geklickt wird, ändert sich der Hash-Link in der URL, der :target-Selektor passt und der entsprechende Bildschirm wird angezeigt.

Ich habe den :checked-Selektor verwendet, um die Bearbeitung einer Nachricht umzuschalten. Jede Nachricht in der Liste ist ein Anker zu ihrer vollständigen Detailansicht. Das winzige bisschen Code :target { left: 0; } war alles, was benötigt wurde, um sie ins Blickfeld zu bringen.
Ein versteckter „Löschen“-Button gleitet herein, wenn der Bearbeitungsbutton ausgewählt ist. Der Button-Text wird über content im :before-Pseudoelement geändert, anstatt ein weiteres Element zum Umschalten von Zuständen zu erstellen. Der „Löschen“-Nachrichtenbutton blendet einfach die nächste Nachricht in der Liste aus, wenn sie ausgewählt ist.
Jede Nachricht wurde dann beim Treffen des :target-Selektors angezeigt und glitt von links herein (es gab Schwierigkeiten beim Übergang von rechts). Eine komplexere Verkettung von Checkboxen wurde verwendet, um Checkboxen für jeden Thread in der Nachricht einzublenden (während seine Abmessungen leicht verändert wurden) und eine weitere Checkbox unten einzublenden, um das Löschen zu bestätigen. Unter Verwendung derselben Methode wie zuvor wurde die Nachricht über :checked + div { display: none; } ausgeblendet.
(Demo funktioniert auf Mobilgeräten, ist aber eher eine Desktop-Erfahrung – sie an einen mobilen Bildschirm anzupassen wäre trivial einfach.)
Vorteile
- Kein JavaScript!
- Nur ein Ankerlink, eine ID und ein einfacher Pseudoselektor sind erforderlich, um dies zu erreichen.
- Ist nicht vollständig von der Markup-Reihenfolge abhängig. Jedes Objekt benötigt nur eine ID oder eine ID im Selektor. Z.B.: #hd:target nav
- Fällt auf Anker zurück, wenn nicht unterstützt.
- Automatisch zum Element scrollen, sodass eine feste Position nicht erforderlich ist.
Nachteile / Probleme
- Es scheint nur ein- und auszublenden, wenn es links außerhalb des Bildschirms positioniert ist, andere blenden erst nach Verlassen von :target über.
- Nur ein Element kann auf dem Bildschirm dargestellt werden.
- Die Verwendung eines rechten Offsets hat Chrome völlig verwirrt, es zeigte fälschlicherweise die letzte ID als anvisiert an.
Fazit
Ich bin immer daran interessiert, was wir nur mit Markup und CSS erstellen können. Obwohl dies ein Hack ist und für die Produktion möglicherweise nicht ideal ist, zeigt es zumindest, dass wir keine Kompromisse bei Design oder Interaktivität eingehen müssen, wenn das Gerät/der Benutzer kein JavaScript hat und auf das einfache Scrollen des gewünschten Elements zur Ansicht zurückfallen kann.
Verwandte Links
- Aaron Gustafson: Erstellen Sie eine intelligente mobile Navigation ohne Hacks
- Luke Wroblewski: Multi-Device-Layout-Muster
- Brad Frost: Responsive Navigationsmuster
Nette Demo, aber ein paar Anmerkungen
– der ~ Selektor (verwendet mit :checked) wird von Android 2.1 nicht unterstützt („Wo ist die Navigation/Seitenleiste?“) (+ wird unterstützt)
– target und Zurück-Button (Verlauf) können ein „seltsames“ Verhalten für den Endbenutzer haben (
in der Demo wird der Zurück-Button wegen des fest positionierten Headers nicht verwendet, aber fest und mobil… Auf einer „echten“ Website kann es einige Probleme verursachen, mehr für eine Seitenleiste als für eine Navigation )
Brillant, besonders die Verkettung von :checked, das hat mich umgehauen!
Vielen Dank für die wundervolle Demo, Chris und Matty. :)
Schöner Beitrag, ich werde mir das genauer ansehen, da ich auch die Einfachheit von HTML in Verbindung mit einigen schönen CSS-Funktionen mag, um Dinge zu erledigen.
Da die Unterstützung für :target etwas gemischt zu sein scheint, wäre es dann nicht besser, etwas wie jQuery scrollTo oder eine CSS-Animation zu verwenden?
Meine Präferenz wäre, jQuery zu verwenden, um der Navigation eine Klasse zuzuweisen und CSS-Übergänge zu verwenden, aber es könnte verwendet werden, um die Erfahrung für mobile Benutzer ohne JS zu verbessern. Ein Fallback für Nicht-
:target-Unterstützung wäre ideal, aber wie man das ohne JavaScript herausfindet… ich bin mir nicht sicher.Gut gemacht… ich werde es versuchen.
Das ist sehr cool!
Noch ein guter Beitrag von dir, Chris. Werde daraus definitiv etwas machen. Danke!
Dies ist eine ziemlich coole Technik, aber leider fallen viele dieser sehr ausgefeilten CSS-Techniken in der Praxis etwas ab. Zum Beispiel schaffte es auf Android 4.0 das Anklicken einer Nachricht in der ursprünglichen Nachrichteliste oft nicht, die Konversation anzuzeigen.
Meiner Erfahrung nach unterstützen Browser, die erweiterte Selektoren und Übergänge unterstützen, auch jQuery. Obwohl jQuery dem Seitengewicht etwas hinzufügt, finde ich es zuverlässiger.
Dennoch eine interessante Fallback-Lösung und Übung, und dafür danke ich Ihnen.
Es ist eine wirklich interessante Technik, aber wie andere schon sagten, ist :target nicht zuverlässig genug, um dies praktikabel zu machen. Ich vermute (ohne Beweise dafür), dass JavaScript weiter verbreitet und daher praktikabler ist.
Meine Präferenz ist die Verwendung von JavaScript, um eine Klasse zuzuweisen/zu entfernen, native CSS-Übergänge zu verwenden und einen Fallback bereitzustellen, wenn JavaScript nicht verfügbar ist. Ich bin mir sicher, dass dies auf einigen Geräten immer noch fehlschlägt, aber es scheint einigermaßen zuverlässig.
Davon abgesehen liebe ich diese Art von Ideen und Artikeln. Ich bin immer enorm beeindruckt von der Kreativität anderer Designer und Entwickler.
Ich liebe die Tatsache, dass es Magic Mouse Swiping unterstützt, um zwischen den Nachrichten und dem Posteingang zu wechseln. Woher kommt diese Unterstützung?
Danke Chris, nette Demo.