Mit CSS gelöst! Logisches Styling basierend auf der Anzahl der vorhandenen Elemente

Avatar of Una Kravets
Una Kravets am

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

Dieser Beitrag ist der dritte in einer Reihe über die Macht von CSS.

Artikelserie

  1. SVG-Hintergründe einfärben
  2. Dropdown-Menüs
  3. Logisches Styling basierend auf der Anzahl der vorhandenen Elemente (dieser Beitrag)

Wussten Sie schon, dass CSS Turing-vollständig ist? Wussten Sie schon, dass Sie damit ziemlich ernsthafte logische Stylings durchführen können? Nun, das können Sie! Sie müssen nicht alle Ihre logikbasierten Styling-Regeln in JavaScript festlegen oder nicht einmal JavaScript verwenden, um Klassen festzulegen, gegen die Sie stylen. In vielen Fällen kann CSS dies selbst erledigen. Ich entdecke jeden Tag neue CSS-Tricks, und das lässt mich es nur noch mehr lieben.

Dieses Jahr habe ich bei Bustle Digital Group angefangen zu arbeiten. In den Medien, wie bei vielen Produkten, baut das Engineering-Team eine Plattform, die alle Anwendungsfälle unterstützen soll. Unser CMS bietet Autoren und Redakteuren die Möglichkeit, Artikel zu erstellen sowie Seiten zu kuratieren und die Einbindung von Anzeigen zu steuern.

Im Gegensatz zur Arbeit mit einer statischen Website hat das Engineering-Team keine vollständige Kontrolle über die vom Benutzer eingegebenen Daten, sodass Designentscheidungen und Regeln für eine gute Benutzererfahrung getroffen werden müssen. Einige dieser Szenarien, mit denen wir im digitalen Medienbereich konfrontiert waren, haben mich wirklich dazu inspiriert, nach Möglichkeiten zu suchen, CSS zur Lösung dieser UI-Herausforderungen einzusetzen, und da kamen Lösungen, die diese Idee beinhalten, wirklich in meinen Fokus.

Schauen wir uns also einige Beispiele an!

Beispiel 1: Binäre Zustände

Ein oft vergessener und *sehr* nützlicher Selektor ist der Pseudo-Selektor :empty. Er ermöglicht es Ihnen, Elemente basierend darauf zu stylen, ob sie Inhalt enthalten oder nicht. Hallo leere Zustände! Leere Zustände sind eine großartige Möglichkeit, Ihre Benutzer zu erreichen und Persönlichkeit in Ihre App zu bringen, und Sie können diese Persönlichkeit direkt aus Ihrem CSS einbringen.

In diesem Beispiel haben wir eine Liste von einem Benutzer. Dies könnten Beiträge sein, die der Benutzer (als Autor) veröffentlicht hat, oder gespeicherte Artikel, die ein Benutzer (als Redakteur) gespeichert hat. Die Anwendungsfälle sind hier wirklich endlos. Anstatt JavaScript einzubinden, können wir Pseudo-Elemente verwenden, um Bilder, Stile und Text einzufügen.

Zeichnungen veranschaulichen bedingt angewendete Stile, basierend auf keinen Elementen (links) versus angezeigten Elementen (rechts) in der Liste.

Unsere Lösung hier sind bloße drei Codezeilen

div:empty:after {
  content: 'oh no...';
}

Sie können auch ein :before Pseudo-Element hinzufügen, um Bilder oder andere gewünschte Inhalte einzufügen. Alternativ kann der :not Pseudo-Selektor in *Kombination* mit :empty verwendet werden, um eine :not(:empty) Regel zu erstellen und alle Elemente zu stylen, die nicht leer sind und daher Kinder enthalten.

Siehe den Pen Empty States von Una Kravets (@una) auf CodePen.

Hinweis: Diese Demo dient nur zur Veranschaulichung. Es wird *nicht* empfohlen, Inhalte für Barrierefreiheitszwecke in Pseudo-Elemente einzufügen. Sie können die gleiche Technik verwenden, um :empty oder :not(:empty) Elemente anzusprechen, um Stile auf Kindelemente anzuwenden, die für Screenreader zugänglicher sind.

Erweiterte numerische Auswahl

Das war ein schönes, einfaches Beispiel, aber wir können viel komplexer werden als diese binäre Wahl von Kindelementen in CSS, und dazu verwenden wir den Pseudo-Selektor :nth-child! CSS-Tricks hat ein großartiges Werkzeug, das Ihnen hilft, mit der :nth-child Auswahl zu testen und zu experimentieren, und es kann sich als sehr nützlich erweisen, wie einige der Beispiele zeigen werden.

Aber bevor wir zu diesen kommen, wie funktioniert das genau?

Der Kern des Codes ist dieser, wobei div für ein beliebiges Geschwisterelement steht und x für die Zahl, die wir zur Bestimmung von Stilumbrüchen verwenden.

div:first-child:nth-last-child(n + x),
div:first-child:nth-last-child(n + x) ~ div

Die Verwendung von :nth-last-child anstelle von :nth-child zur Auswahl ermöglicht es uns, vom *Ende* einer Serie anstatt vom Anfang auszugehen. Wenn wir :nth-last-child(n + x) auswählen, wählen wir den x-Wert, beginnend vom Ende. Wenn x = 3, würde das so aussehen

Illustration, wie :nth-last-child(3) das dritte Element vom Ende der Liste auswählt.

Wenn wir nun Werte von n + 3 zählen wollen, wählen wir alle Elemente aus, die **3 oder mehr als 3 vom Ende** entsprechen. Beginnend mit n = 0 (was 0 + 3 bedeuten würde, und das 4. Element wäre das erste vom Ende nach 3). Es sieht so aus

Illustration, wie :nth-last-child(n+3) alle Elemente auswählt, die 3 oder mehr als 3 vom Ende entsprechen.

Das ist ein guter Anfang, aber die Idee hier ist, *alle* Elemente bedingt zu stylen, basierend darauf, wie viele vorhanden sind. Wir müssen also mit diesen Bedingungen arbeiten, aber *alle* Elemente auswählen. Beginnen wir mit der Auswahl des ersten Elements. Wir müssen eine Bedingung erstellen, um zu sehen, ob die gesamte Auswahl für das Styling qualifiziert ist, und dann mit diesem ersten Geschwisterelement beginnen.

Ohje. Wir haben zu diesem Zeitpunkt nur das erste Element ausgewählt und wollen *alle Elemente* auswählen. Glücklicherweise können wir den superpraktischen benachbarten Geschwisterselektor (~) dafür verwenden!

Wenn wir unser letztes Beispiel auf :first-child:last-child(n + 3) ~ * anpassen, werden alle Elemente außer dem ersten ausgewählt, wie wir es wollen.

Nun, jetzt sehen Sie alle Elemente, die dem ersten Element folgen, ausgewählt, aber wir vermissen das erste, also müssen wir zwei Selektoren verwenden, und somit wird die endgültige Antwort

Die Kombination beider vorheriger Beispiele wählt alle Elemente in der Liste aus.

Beispiel 2: Listenformatierung

Sagen wir, Sie möchten am Ende eines Artikels einige Credits auflisten. Sie haben Platz zum Füllen, und die meisten Artikel haben eine kleine Anzahl von Credits, aber es gibt Ausnahmen, die eine hohe Produktionsqualität haben und bei denen viele Leute an der Erstellung beteiligt waren. Wir wollen sicherstellen, dass beide gute visuelle Erlebnisse bieten, und das können wir allein mit CSS tun.

Hier ist der Plan: Wenn es vier oder weniger Credits gibt, listen wir sie im Bullet-Format auf. Lassen Sie sie vertikalen Raum einnehmen, um den Block entsprechend zu füllen. Sobald wir fünf oder mehr Credits aufgelistet haben, wandeln wir diese Liste in ein horizontales Format um, um den Leser nicht zu überfordern. Das ist schließlich eine kleine Credit-Box!

Illustrationen einer vertikalen unsortierten Liste (links) und einer horizontalen Liste, getrennt durch Semikolons (rechts).

Wir können die Anzahl der verfügbaren Elemente überprüfen und sie als block-Elemente stylen, *bis* wir unsere Grenze erreichen. An diesem Punkt wechseln wir zum inline-Styling und fügen ein Pseudo-Element hinzu, um die Daten visuell zu trennen.

/* 5 or more items display next to each other */
li:first-child:nth-last-child(n + 5),
li:first-child:nth-last-child(n + 5) ~ li {
  display: inline;
}

/* Adds semicolon after each item except the last item */
li:first-child:nth-last-child(n + 5) ~ li::before {
  content: ';';
  margin: 0 0.5em 0 -0.75em;
}

:nth-first-child:nth-last-child(n + 5) ermöglicht es uns zu sagen: „Beginne mit dem ersten Kind und wende Stile auf dieses Kind und jedes Geschwisterelement danach an, wenn das ursprüngliche Kind fünf oder mehr Geschwister hat.“ Klingt das verwirrend? Nun, es funktioniert.

li:first-child:nth-last-child(n + 5) wählt das erste Listenelement aus, und li:first-child:nth-last-child(n + 5) ~ li wählt jedes Listenelement nach dem anfänglichen aus.

Siehe den Pen vrQBMv von Una Kravets (@una) auf CodePen.

Beispiel 3: Bedingter Karussell

Mit dieser Technik stylen wir ein Karussell, um es responsiv zu gestalten. Bei großer Größe möchten Sie, dass es in der Mitte der Seite zentriert ist, wenn es drei Elemente enthält. Aber wenn es genügend Elemente hat, um den Bildschirm horizontal zu füllen, lassen Sie es linksbündig für den Benutzer zum Durchwischen ausrichten.

Illustrationen eines Karussells mit drei Elementen (links) und mehr als drei Elementen (rechts).

Was wir hier tun können, ist, die Elemente so zu dehnen, dass sie auf den Bildschirm passen, es sei denn, wir haben zu viele Elemente und sie würden einen Überlauf erfordern. An diesem Punkt setzen wir voll auf diesen Überlauf und stellen die Karussellfunktionen zur Schau, indem wir Scrollbarkeit mit Pfeilen signalisieren und den Abstand zwischen den Elementen erhöhen. Darüber hinaus fügen wir einen festen Pfeil-Button hinzu, um zu zeigen, dass wir die Elemente durchscrollen können, und binden JavaScript-Ereignisse an, um das Karussell scrollbar zu machen.

Wir können dasselbe wie oben in Bezug auf die Technik tun, aber wir werden *auch* nur das first-child verwenden, um ein arrow-Div zu erkennen und es in der UI anzuzeigen. Das HTML würde so aussehen

<ul>
  <li>
    <div class="box">1</div>
  </li>
  <li>
    <div class="box">2</div>
  </li>
  ...
  <button class="arrow">——></button>
</ul>

Es ist nicht ideal, leere Elemente im DOM zu haben, aber arbeiten Sie mit mir. Es ist immer noch ein cleverer Hack. Wir stylen den .arrow-Button so, dass er für das DOM und Screenreader mit visibility: hidden unsichtbar ist, es sei denn, die Bedingungen gelten (in diesem Fall, wenn vier oder mehr Elemente vorhanden sind). An diesem Punkt geben wir ihm eine sichtbare Anzeige (display: block), Stil und positionieren ihn entsprechend.

li:first-child:nth-last-child(n + 5) ~ .arrow {
  display: block;
  position: sticky;
  ...
}

Siehe den Pen Box Alignment von Una Kravets (@una) auf CodePen.

Weitere Informationen!

Bei meiner Recherche für diesen Beitrag habe ich einen ausgezeichneten Beitrag von Heydon Pickering zu dieser Technik namens Quantity Queries und ein weiteres Beispiel von Lea Verou entdeckt! In der Kommentarzeile von Heydons Beitrag merkt Paul Irish an, dass dies eine langsamere Methode zur Auswahl von Elementen ist, also verwenden Sie sie vielleicht mit Vorsicht.