Das Sass-Ampersand

Avatar of Richard Finelli
Richard Finelli am

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

Das & ist ein äußerst nützliches Feature in Sass (und Less). Es wird beim Verschachteln verwendet. Es kann eine nette Zeitersparnis sein, wenn man weiß, wie man es benutzt, oder eine kleine Zeitverschwendung, wenn man damit kämpft und den gleichen Code in regulärem CSS hätte schreiben können.

Mal sehen, ob wir es wirklich verstehen können.

Grundlegendes Verschachteln

.parent {
  .child {}
}

Dies kompiliert zu

.parent .child {}

Sie können beliebig tief verschachteln, aber es ist eine gute Praxis, es auf ein oder zwei Ebenen zu beschränken, um übermäßig spezifische Selektoren zu vermeiden (die weniger nützlich und schwerer zu überschreiben sind).

Hinzufügen einer weiteren Klasse

Das & ist praktisch, wenn Sie verschachteln und einen spezifischeren Selektor erstellen möchten, wie z. B. ein Element, das *beide* von zwei Klassen hat, wie hier

.some-class.another-class { }

Sie können dies beim Verschachteln tun, indem Sie das & verwenden.

.some-class {
  &.another-class {}
}

Das & bezieht sich beim Verschachteln immer auf den übergeordneten Selektor. Denken Sie daran, dass das & entfernt und durch den übergeordneten Selektor ersetzt wird. Wie hier:

Der "Aha"-Moment!

Nehmen Sie dieses Sass

.parent {
  .child {}
}

Dies kann tatsächlich als Kurzform für das Verschachteln mit dem & betrachtet werden.

.parent {
  & .child {}
}

Diese beiden Beispiele werden also beide zu demselben Ergebnis kompiliert.

.parent .child {}

Das Beispiel mit dem & ist nichts anderes als das Beispiel ohne das &. Verschachtelung *ohne* das & ist eine Kurzform für Verschachtelung *mit* ihm. Wir können das & als Mechanismus betrachten, der es uns ermöglicht, den übergeordneten Selektor dort zu platzieren, wo wir ihn in unserem untergeordneten Selektor benötigen. Es ermöglicht uns, mit Änderungen zu verschachteln. Schauen wir uns weitere Beispiele an.

Verwendung von & mit Pseudoklassen

Sie können Pseudoklassen auf eine Klasse auf eine viel weniger repetitive Weise mit dem & schreiben.

.button {
  &:visited { }
  &:hover { }
  &:active { }
}

Dies kompiliert zu

.button:visited { }
.button:hover { }
.button:active { }

Das & erlaubt es uns in diesem Fall, .button direkt neben Pseudoklassen zu positionieren, ohne Wiederholungen im Quellcode. Wenn wir das & aus diesem Beispiel weglassen würden, würde grundlegendes Verschachteln einen Leerraum dazwischen setzen, wie hier...

.button :hover

...was nicht dasselbe ist.

Verwendung von & mit >, +, und ~

Die Verwendung von & mit dem Kind-Kombinator >, dem direkten Geschwister-Kombinator + und dem allgemeinen Geschwister-Kombinator ~ ist ein Kinderspiel. Zuerst dachte ich, man müsse das & verwenden, aber

// You don't actually have to do this.
// Here, the ampersand is implied.
.button {
  & > span { }
  & + span { }
  & ~ span { }
}

Das Weglassen des & aus dem Selektor funktioniert hier.

// This compiles the same as above
.button {
  > span { }
  + span { }
  ~ span { }
}

Beide Beispiele werden zu folgendem CSS kompiliert.

.button > span { }
.button + span { }
.button ~ span { }

Qualifizierung basierend auf dem Kontext

Verschachtelte Selektoren müssen nicht unbedingt mit dem Ampersand beginnen. Sie können einen Selektor qualifizieren, indem Sie das & auf der rechten Seite platzieren.

.button {
  body.page-about & { }
}

Wir positionieren den übergeordneten Selektor genau dort, wo wir ihn brauchen. Dies ist sehr nützlich, um einen Selektor basierend auf einem anderen übergeordneten Element zu qualifizieren. Dies wird kompiliert zu

body.page-about .button {}

Das bedeutet, wähle die Klasse button nur aus, wenn sie ein Kind von body mit einer Klasse page-about ist.

Anpassen der Definition von &

Denken Sie daran, dass das & nicht nur durch den übergeordneten Selektor ersetzt wird, sondern durch den *kompilierten* übergeordneten Selektor.

Dies ist wichtig, wenn mehr als zwei Ebenen tief verschachtelt wird und mehr als eine Ebene ein & hat. Diese nächsten beiden verrückten Beispiele verdeutlichen diesen Punkt.

Verrücktes, aber funktionierendes Beispiel Nr. 1

Schreiben Sie keine Selektoren, die so aussehen

.parent {
  .child {
    & div & & > a {}
  }
}

Für jedes & wird es durch den kompilierten übergeordneten Selektor ersetzt. Daher fügen wir jedes Mal, wenn ein & vorhanden ist, .parent .child ein. Hier ist das kompilierte CSS.

.parent .child div .parent .child .parent .child > a {}

Verrücktes, aber funktionierendes Beispiel Nr. 2

.parent {
  .child {
    .grand-child & {
      &.sibling { }
    }
  }
}

Um dieses CSS mental zu kompilieren, beginnen Sie auf der obersten Ebene und arbeiten Sie sich nach unten vor, schälen Sie die äußeren Ebenen ab und ersetzen Sie das & durch den neuen kompilierten übergeordneten Selektor.

Hier ist es kompiliert.

.grand-child .parent .child.sibling {}

Was das & nicht ist

Ich habe festgestellt, dass ich das & manchmal für etwas verwendet habe, wofür es nicht gedacht war. Das & erlaubt es Ihnen nicht, selektiv in Ihrem verschachtelten Selektorbaum zu einer bestimmten Stelle aufzusteigen und nur einen kleinen Teil des kompilierten übergeordneten Selektors zu verwenden, den Sie verwenden möchten. Ich wollte schon einmal etwas wie das hier tun.

.grand-parent {
  .parent {
    &(1) .child {} // Trying to get `.parent`, not `.grand-parent .parent`
  }
}

Meine Absicht war, dass das & nur durch .parent ersetzt wird, in der Hoffnung, dies zu kompilieren.

.parent .child {}

Aber das funktioniert nicht.

Das & ist immer der vollständig kompilierte übergeordnete Selektor.

@at-root zur Rettung

Es ist erwähnenswert, dass @at-root es Ihnen ermöglicht, Ihre Verschachtelungsstruktur vollständig zu verlassen und zum "Root" Ihres Verschachtelungsbaums zu gelangen.

.grand-parent {
  .parent {
    @at-root .child {}
  }
}

Wir sind aus dem Verschachtelungsbaum zu diesem kompilierten CSS teleportiert.

.child {}

Das ist schön. Aus organisatorischer Sicht ist der gesamte Code immer noch zusammengefasst, was als unbesungener Vorteil des Verschachtelns angesehen werden kann. @at-root kann helfen, Spezifitätsstufen niedrig zu halten, da Sie nicht mehr den kompilierten übergeordneten Selektor haben, um die Spezifität zu erhöhen. Und das alles, während Ihr Code durch Verschachtelung konzeptionell organisiert bleibt.

.grand-parent {
  .parent {
    @at-root body.page-about .child {}
  }
}

Kompiliertes CSS

body.page-about .child {}

Es gibt ein paar andere Anwendungsfälle für das &, die Spaß machen können.

Verdoppelung der Spezifität

Manchmal müssen Sie die Spezifität einer CSS-Bibliothek von Drittanbietern überwinden, um den Stil zu übernehmen.

.parent.parent {}

Es ist viel weniger einschüchternd als die Verwendung einer ID, eines Inline-Stils oder !important und könnte Vorteile gegenüber der Qualifizierung des Selektors mit einem beliebigen übergeordneten Element haben. Die Spezifitätsstufe wird nicht basierend auf dem Kontext eines Selektors erhöht, sondern nur durch sich selbst. Mit dem & können Sie dasselbe tun, wie hier.

.parent {
  &#{&} { }
}

Die Interpolationsklammern #{ } sind erforderlich, da zwei aufeinanderfolgende Ampersands ungültiges Sass sind.

Ändern des Ampersands

Obwohl Sie keine zwei aufeinanderfolgenden Ampersands ohne Interpolationsklammern haben können – wie wir bereits in unserem Pseudoklassenbeispiel gezeigt haben –, können Sie einen anderen Selektor an das Ampersand anfügen. Das Anfügen an das Ampersand funktioniert gut mit Modifikatorklassen.

.btn {
  &-primary {}
  &-secondary {}
}

Kompiliertes CSS

.btn-primary {}
.btn-secondary {}

Dies kann sehr nützlich sein, wenn Sie eine Namensmethodik (z. B. BEM) verwenden, die Dash- und Unterstrich-kombinierte Klassen anstelle von kombinierten Selektoren verwendet.

Fazit

Das Ampersand in Kombination mit Verschachtelung ist eine großartige Funktion. Sobald Sie wissen, was es tut, kann das Verfassen Ihres Sass einfacher, schneller und fehlerfreier werden.

Hier sind ein paar andere Artikel speziell über das Ampersand, zu Ihrer Referenz.