Einige extrem praktische `:nth-child`-Rezepte als Sass Mixins

Avatar of Adam Giese
Adam Giese am

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

Es gibt kein Einheits-Styling. Eine Bildergalerie mit drei Bildern muss möglicherweise anders gestylt werden als eine Bildergalerie mit zwölf. Es gibt einige coole Tricks, mit denen Sie Ihrer CSS Logik hinzufügen können, die auf Zahlen basiert! Mit :nth-child und :nth-last-child können Sie erstaunlich komplexe Informationen abrufen, ohne jemals Ihr Stylesheet verlassen zu müssen.

Dieser Beitrag setzt ein grundlegendes Verständnis der Funktionsweise des `:nth-child`-Pseudo-Selectors voraus. Wenn Sie eine schnelle Auffrischung benötigen, hat Chris einen grossartigen Beitrag zu diesem Thema.

Schreiben komplexer :nth-child()-Selektoren

Möglicherweise wissen Sie, dass es neben `:nth-child` auch das verwandte `:nth-last-child` gibt. Es funktioniert genauso wie `:nth-child`, ausser dass es vom Ende des Elternelements aus gezählt wird. Sie können beispielsweise die ersten drei Kinder eines Elternelements mit dem Selektor :nth-child(-n + 3) auswählen. Sie können :nth-last-child(-n + 3) verwenden, um die letzten drei auszuwählen. Sehen wir uns eine ungeordnete Liste als Beispiel an.

Sehen Sie den Pen 1. Die letzten drei auswählen von Adam Giese (@AdamGiese) auf CodePen.

Ähnlich können Sie :nth-last-child(n + 4) verwenden, um alle Kinder ausser den letzten drei auszuwählen.

Sehen Sie den Pen 2. Alle ausser den letzten drei auswählen von Adam Giese (@AdamGiese) auf CodePen.

Die wirkliche Magie geschieht, wenn Sie :nth-last-child mit :first-child kombinieren. Indem Sie beide Selektoren verwenden, um zu prüfen, ob ein Element sowohl das erste Kind des Elternelements als auch eines der letzten drei Elemente ist, können Sie das erste Element eines Elternelements stylen, nur wenn höchstens drei Elemente vorhanden sind.

li:nth-last-child(-n + 3):first-child {
  /* your styling here */
}

Weiter mit unserem Listenbeispiel, hier ist eine Möglichkeit, dies zu visualisieren

Sehen Sie den Pen 3. "first-child" und "last three" verketten von Adam Giese (@AdamGiese) auf CodePen.

Umgekehrt können Sie li:nth-last-child(n + 4):first-child verwenden, um das erste Element einer Liste mit vier oder mehr Elementen auszuwählen.

Sehen Sie den Pen 4. Mindestens drei Selektor von Adam Giese (@AdamGiese) auf CodePen.

Ziemlich cool, oder? Aber wahrscheinlich möchten Sie mehr als nur das erste Element in einer Liste stylen. Mit dem allgemeinen Geschwisterselektor können Sie alle Listenelemente stylen, die diesem ersten Element folgen. Fügen Sie beide Selektoren, getrennt durch ein Komma, hinzu, und Sie können alle Elemente auswählen.

li:nth-last-child(n + 4):first-child,
li:nth-last-child(n + 4):first-child ~ li {
  /* your styling here */
}

Sehen Sie den Pen 5. Mindestens vier Selektor von Adam Giese (@AdamGiese) auf CodePen.

Dies eröffnet viele interessante Möglichkeiten! Sie müssen sich auch nicht nur auf die Zählung der Gesamtzahl der Elemente beschränken. Durch das Verketten von :first-child und :nth-last-child können Sie prüfen, ob ein beliebiger gültiger :nth-child-Ausdruck für die Gesamtzahl der Elemente gilt. Sie können Styling schreiben, wenn es eine Gesamtanzahl von ungeraden Kindern gibt, wenn es genau sieben Kinder gibt oder wenn es 3n + 2 Kinder gibt.

Ein realer Anwendungsfall für diese Technik ist das Styling von Dropdown-Menüs, die automatisch von einem CMS generiert wurden. Als Beispiel betrachten wir den von der WordPress-Funktion wp_nav_menu() generierten Code, der zur besseren Lesbarkeit bereinigt wurde.

Sehen Sie den Pen WordPress-Menü nth-child-Beispiel von Adam Giese (@AdamGiese) auf CodePen.

Das sieht ziemlich standardmässig aus. Bewegen Sie den Mauszeiger über das Menüelement Mitglieder und beachten Sie die Untermenüelemente.

Betrachten wir nun dasselbe Menü mit einigen zusätzlichen Mitgliedern.

Sehen Sie den Pen WordPress-Menü nth-child-Beispiel, mehr Kinder von Adam Giese (@AdamGiese) auf CodePen.

Wow! Das Styling, das für vier Elemente gut funktionierte, skaliert nicht gut auf zwölf. Durch Anwenden des vorherigen Beispiels können Sie das Standardmenü von WordPress rein im Stylesheet stylen: Sie müssen keinen benutzerdefinierten Filter schreiben, um die Klasse je nach Anzahl der Menüelemente zu ändern: Sie können das Styling im Stylesheet belassen.

Sehen Sie den Pen WordPress-Menü nth-child-Beispiel, kompakt von Adam Giese (@AdamGiese) auf CodePen.

Hier sind einige andere mögliche Anwendungsfälle.

Einschränkungen

Es gibt viele coole Dinge, die Sie mit :nth-child tun können. Es gibt jedoch einige Einschränkungen. Zum Beispiel können Sie nicht das Elternelement stylen, nur die Kindelemente. Sie können kein Styling für eine ul basierend auf der Anzahl der darin enthaltenen li-Elemente hinzufügen.

Eine weitere Überlegung ist, ob :nth-child oder :nth-of-type verwendet werden soll. Die Verwendung von :nth-child wählt alle Elemente aus, was möglicherweise gewünscht ist oder auch nicht. Wenn Sie beispielsweise ein .post-content basierend auf der Anzahl der Absätze stylen möchten, würden Sie p:nth-of-type verwenden. Leider können Sie mit dieser Methode nur Elemente nach (und einschliesslich) dem ersten Absatz-Tag stylen. Wenn sich am Anfang des Inhalts ein h2-Tag befand, könnten Sie die Überschrift nicht basierend auf der Anzahl der p-Tags stylen. Ausserdem funktioniert `nth-of-type` nur bei Elementen: Sie könnten die Menge einer bestimmten Klasse nicht überprüfen.

Ich habe festgestellt, dass dieser Trick am besten bei Elementen mit vorhersehbaren Geschwistern funktioniert. li ist ein perfekter Kandidat, da es die einzigen gültigen Kinder von ul und ol sind. Automatisch generierte Inhalte können ebenfalls gut funktionieren.

Abstraktionen

Das ist ein cooler Trick, aber leider ist die Syntax etwas umständlich. Wenn Sie Sass verwenden, können Sie jedoch problemlos eine Abstraktionsschicht hinzufügen, um die Verwendung erheblich zu erleichtern! Dies macht die Verwendung dieser komplexen Selektoren viel lesbarer und intuitiver.

Da all diese Selektoren auf einem einzigen Muster basieren, können Sie mit einem allgemeinen Mixin beginnen

@mixin has-nth($expression, $element: '*') {
  &:nth-last-child(#{$expression}):first-child,
  &:nth-last-child(#{$expression}):first-child ~ #{$element} {
    @content;
  }
}

Was im SCSS ungefähr so aufgerufen würde

li {
  @include has-nth('n + 4', 'li') { //four or more
    /* your styling here */
  }
}

Während dies definitiv weniger unübersichtlich ist als reines CSS, können Sie eine weitere Abstraktionsschicht hinzufügen, indem Sie einige weitere Mixins definieren. Hier ist ein Beispiel, wie man ein `at-least`-Mixin schreibt.

@mixin at-least($quantity, $element: '*') {
  @include has-nth('n + #{$quantity}', $element) {
    @content;
  }
}

Diese würden im Code wie folgt aufgerufen werden

li {
  @include at-least(4, 'li') { // four or more
    // styling goes here...
  }
}

Definitiv eine Verbesserung der Lesbarkeit! Sie können sogar Mixins verketten, indem Sie sie verschachteln.

Hier finden Sie eine Sammlung von Sass-Mixins, die komplexe nth-child-Logik verwenden.

Zukünftige Selektoren

Es gibt einige zusätzliche Funktionen, die sich derzeit im W3C Editor's Draft befinden und die Flexibilität dieser Technik erheblich erhöhen könnten. Eines davon ist das Argument selector list für nth-child. Dies funktioniert, indem dem nth-child-Selektor ein zusätzliches optionales Argument hinzugefügt wird. Dies funktioniert ähnlich wie bei nth-of-type, ausser dass es für beliebige Selektoren gilt, nicht nur für Elemente. Wenn Sie beispielsweise den Selektor li:nth-child(odd of .active) verwenden könnten, um jeden zweiten Listeneintrag mit der Klasse active zu stylen. Mit dieser Funktion können wir die Menge einer bestimmten Klasse erkennen: zum Beispiel

li.active:nth-last-child(n + 5 of .active).first-child,
li:nth-last-child(n + 5 of .active).first-child ~ li.active {
  /* styling goes here... */
}

Dies stylt alle aktiven Listenelemente, wenn mindestens fünf vorhanden sind. Sie können mehr über die Selektorliste hier lesen. Die Browserunterstützung ist derzeit sehr begrenzt; sie ist nur in Safari (sowohl iOS als auch OSX) verfügbar.

Eine weitere Funktion ist der relationale Pseudo-Klassen-Selektor. Dieser vorgeschlagene Selektor akzeptiert ein selector list-Argument und stimmt überein, wenn der Selektor relativ zum Basisselektor vorhanden ist. Sie können beispielsweise ul:has(li) stylen, um Styling für Listen mit mindestens einem li hinzuzufügen. Sie können auch viel kompliziertere Selektoren hinzufügen: .post-content:has(h1, h2, h3, h4, h5, h6) kann jedes .post-content mit mindestens einem Überschriftenelement stylen. Mit dieser Funktion, kombiniert mit einigen der erweiterten nth-child-Rezepte, die wir gelernt haben, können wir ul:has(li:nth-last-child(n + 5):first-child) schreiben, um jede ul mit mindestens fünf li zu stylen.

Derzeit ist das Styling nach Menge hauptsächlich für das Styling von Elementen mit vorhersagbaren Geschwistern nützlich, wie Listen oder Tabellen. Wenn diese beiden Funktionen unterstützt werden, wird diese Technik viel flexibler sein.