@extend

Beim Gestalten einer Seite gibt es oft Fälle, in denen eine Klasse alle Stile einer anderen Klasse sowie ihre eigenen spezifischen Stile haben soll. Zum Beispiel ermutigt die BEM-Methodik Modifikator-Klassen, die auf denselben Elementen wie Block- oder Elementklassen angebracht werden. Dies kann jedoch zu unübersichtlichem HTML führen, ist fehleranfällig, wenn beide Klassen vergessen werden, und kann nicht-semantische Stilbedenken in Ihr Markup einbringen.

<div class="error error--serious">
  Oh no! You've been hacked!
</div>
.error {
  border: 1px #f00;
  background-color: #fdd;
}

.error--serious {
  border-width: 3px;
}

Die Sass-Regel @extend löst dieses Problem. Sie wird als @extend <selektor> geschrieben und teilt Sass mit, dass ein Selektor die Stile eines anderen erben soll.

Spielplatz

SCSS-Syntax

.error {
  border: 1px #f00;
  background-color: #fdd;

  &--serious {
    @extend .error;
    border-width: 3px;
  }
}
Spielplatz

Sass-Syntax

.error
  border: 1px #f00
  background-color: #fdd

  &--serious
    @extend .error
    border-width: 3px


CSS-Ausgabe

.error, .error--serious {
  border: 1px #f00;
  background-color: #fdd;
}
.error--serious {
  border-width: 3px;
}


Wenn eine Klasse eine andere erweitert, formatiert Sass alle Elemente, die dem Erweiterer entsprechen, so, als ob sie auch der erweiterten Klasse entsprechen würden. Wenn ein Klassenselektor einen anderen erweitert, funktioniert dies genau so, als ob Sie die erweiterte Klasse zu jedem Element in Ihrem HTML hinzugefügt hätten, das bereits die erweiternde Klasse hatte. Sie können einfach class="error--serious" schreiben, und Sass stellt sicher, dass es so formatiert wird, als hätte es auch class="error".

Selektoren werden natürlich nicht nur einzeln in Stilregeln verwendet. Sass weiß, dass es überall dort erweitert, wo der Selektor verwendet wird. Dies stellt sicher, dass Ihre Elemente genau so formatiert werden, als ob sie dem erweiterten Selektor entsprechen würden.

Spielplatz

SCSS-Syntax

.error:hover {
  background-color: #fee;
}

.error--serious {
  @extend .error;
  border-width: 3px;
}
Spielplatz

Sass-Syntax

.error:hover
  background-color: #fee


.error--serious
  @extend .error
  border-width: 3px

CSS-Ausgabe

.error:hover, .error--serious:hover {
  background-color: #fee;
}

.error--serious {
  border-width: 3px;
}

⚠️ Vorsicht!

Erweiterungen werden nach der Kompilierung des restlichen Stylesheets aufgelöst. Insbesondere geschieht dies nach der Auflösung von Elternselektoren. Das bedeutet, wenn Sie @extend .error verwenden, hat dies keine Auswirkungen auf den inneren Selektor in .error { &__icon { ... } }. Es bedeutet auch, dass Elternselektoren in SassScript die Ergebnisse von Erweiterungen nicht sehen können.

Wie es funktioniertWie es funktioniert Permalink

Im Gegensatz zu Mixins, die Stile in die aktuelle Stilregel kopieren, aktualisiert @extend Stilregeln, die den erweiterten Selektor enthalten, so dass sie auch den erweiternden Selektor enthalten. Beim Erweitern von Selektoren führt Sass intelligente Vereinheitlichung durch.

  • Es werden niemals Selektoren wie #main#footer generiert, die keinerlei Elemente abgleichen können.

  • Es stellt sicher, dass komplexe Selektoren so verschachtelt sind, dass sie unabhängig von der Reihenfolge der HTML-Elementverschachtelung funktionieren.

  • Es kürzt redundante Selektoren so weit wie möglich, stellt aber gleichzeitig sicher, dass die Spezifität größer oder gleich der des Erweiterers ist.

  • Es weiß, wann ein Selektor alles abgleicht, was ein anderer tut, und kann sie kombinieren.

  • Es verarbeitet intelligent Kombinatoren, universelle Selektoren und Pseudo-Klassen, die Selektoren enthalten.

Spielplatz

SCSS-Syntax

.content nav.sidebar {
  @extend .info;
}

// This won't be extended, because `p` is incompatible with `nav`.
p.info {
  background-color: #dee9fc;
}

// There's no way to know whether `<div class="guide">` will be inside or
// outside `<div class="content">`, so Sass generates both to be safe.
.guide .info {
  border: 1px solid rgba(#000, 0.8);
  border-radius: 2px;
}

// Sass knows that every element matching "main.content" also matches ".content"
// and avoids generating unnecessary interleaved selectors.
main.content .info {
  font-size: 0.8em;
}
Spielplatz

Sass-Syntax

.content nav.sidebar
  @extend .info


// This won't be extended, because `p` is incompatible with `nav`.
p.info
  background-color: #dee9fc


// There's no way to know whether `<div class="guide">` will be inside or
// outside `<div class="content">`, so Sass generates both to be safe.
.guide .info
  border: 1px solid rgba(#000, 0.8)
  border-radius: 2px


// Sass knows that every element matching "main.content" also matches ".content"
// and avoids generating unnecessary interleaved selectors.
main.content .info
  font-size: 0.8em

CSS-Ausgabe

p.info {
  background-color: #dee9fc;
}

.guide .info, .guide .content nav.sidebar, .content .guide nav.sidebar {
  border: 1px solid rgba(0, 0, 0, 0.8);
  border-radius: 2px;
}

main.content .info, main.content nav.sidebar {
  font-size: 0.8em;
}









💡 Lustige Tatsache

Sie können direkt auf die intelligente Vereinheitlichung von Sass über Selektorfunktionen zugreifen! Die Funktion selector.unify() gibt einen Selektor zurück, der die Schnittmenge zweier Selektoren abgleicht, während die Funktion selector.extend() ähnlich wie @extend funktioniert, aber auf einem einzelnen Selektor.

⚠️ Vorsicht!

Da @extend Stilregeln aktualisiert, die den erweiterten Selektor enthalten, haben deren Stile in der Kaskade Vorrang basierend darauf, wo die Stilregeln des erweiterten Selektors erscheinen, und nicht darauf, wo das @extend erscheint. Dies kann verwirrend sein, aber denken Sie einfach daran: Dies ist der gleiche Vorrang, den diese Regeln hätten, wenn Sie die erweiterte Klasse zu Ihrem HTML hinzufügen würden!

Platzhalter-SelektorenPlatzhalter-Selektoren Permalink

Manchmal möchten Sie eine Stilregel schreiben, die nur zum Erweitern gedacht ist. In diesem Fall können Sie Platzhalter-Selektoren verwenden, die wie Klassenselektoren aussehen, die mit % anstelle von . beginnen. Alle Selektoren, die Platzhalter enthalten, werden nicht in die CSS-Ausgabe aufgenommen, aber Selektoren, die sie erweitern, tun dies.

Spielplatz

SCSS-Syntax

.alert:hover, %strong-alert {
  font-weight: bold;
}

%strong-alert:hover {
  color: red;
}
Spielplatz

Sass-Syntax

.alert:hover, %strong-alert
  font-weight: bold


%strong-alert:hover
  color: red

CSS-Ausgabe

.alert:hover {
  font-weight: bold;
}




Private PlatzhalterPrivate Platzhalter Permalink

Wie Modulmitglieder kann ein Platzhalter-Selektor als privat gekennzeichnet werden, indem sein Name mit - oder _ beginnt. Ein privater Platzhalter-Selektor kann nur innerhalb des Stylesheets erweitert werden, das ihn definiert. Für alle anderen Stylesheets sieht es so aus, als ob dieser Selektor nicht existiert.

ErweiterungsbereichErweiterungsbereich Permalink

Wenn ein Stylesheet einen Selektor erweitert, wirkt sich diese Erweiterung nur auf Stilregeln aus, die in upstream-Modulen geschrieben wurden – das heißt, Modulen, die von diesem Stylesheet mithilfe der Regel @use oder der Regel @forward geladen werden, Modulen, die von diesen Modulen geladen werden und so weiter. Dies trägt dazu bei, Ihre @extend-Regeln besser vorhersagbar zu machen und sicherzustellen, dass sie nur die Stile beeinflussen, die Sie beim Schreiben davon kannten.

⚠️ Vorsicht!

Erweiterungen sind überhaupt nicht mit dem Geltungsbereich versehen, wenn Sie die Regel @import verwenden. Sie beeinflussen nicht nur jedes importierte Stylesheet, sondern auch jedes andere Stylesheet, das Ihr Stylesheet importiert, alles andere, was diese Stylesheets importieren, und so weiter. Ohne @use sind Erweiterungen global.

Obligatorische und optionale ErweiterungenObligatorische und optionale Erweiterungen Permalink

Normalerweise, wenn eine @extend-Anweisung keine Selektoren im Stylesheet findet, gibt Sass einen Fehler aus. Dies schützt vor Tippfehlern oder vor der Umbenennung eines Selektors, ohne die von ihm erbenden Selektoren umzubenennen. Erweiterungen, die erfordern, dass der erweiterte Selektor existiert, sind obligatorisch.

Das ist jedoch möglicherweise nicht immer das, was Sie wollen. Wenn Sie möchten, dass die @extend-Anweisung nichts tut, wenn der erweiterte Selektor nicht existiert, fügen Sie einfach !optional am Ende hinzu.

Erweitern oder Mixins?Erweitern oder Mixins? Permalink

Erweiterungen und Mixins sind beides Wege, Stile in Sass zu kapseln und wiederzuverwenden, was natürlich die Frage aufwirft, wann man welche verwenden soll. Mixins sind offensichtlich notwendig, wenn Sie Stile mit Argumenten konfigurieren müssen, aber was ist, wenn es sich nur um einen Block von Stilen handelt?

Als Faustregel gilt: Erweiterungen sind die beste Option, wenn Sie eine Beziehung zwischen semantischen Klassen (oder anderen semantischen Selektoren) ausdrücken. Da ein Element mit der Klasse .error--serious ein Fehler ist, ist es sinnvoll, dass es .error erweitert. Aber für nicht-semantische Sammlungen von Stilen kann das Schreiben eines Mixins Kopfschmerzen in der Kaskade vermeiden und die Konfiguration im weiteren Verlauf erleichtern.

💡 Lustige Tatsache

Die meisten Webserver komprimieren die von ihnen bereitgestellten CSS mithilfe eines Algorithmus, der sehr gut darin ist, wiederholte Blöcke identischen Textes zu verarbeiten. Das bedeutet, dass Mixins zwar mehr CSS erzeugen als Erweiterungen, aber wahrscheinlich nicht die Menge, die Ihre Benutzer herunterladen müssen, wesentlich erhöhen. Wählen Sie also das Feature, das für Ihren Anwendungsfall am sinnvollsten ist, nicht dasjenige, das das wenigste CSS generiert!

EinschränkungenEinschränkungen Permalink

Nicht zulässige SelektorenNicht zulässige Selektoren Permalink

Kompatibilität (Keine kombinierten Erweiterungen)
Dart Sass
LibSass
Ruby Sass

LibSass und Ruby Sass erlauben derzeit kombinierte Selektoren wie .message.info zur Erweiterung. Dieses Verhalten entspricht jedoch nicht der Definition von @extend: Anstatt Elemente zu formatieren, die dem erweiternden Selektor entsprechen, als ob er class="message info" hätte, was von Stilregeln betroffen wäre, die entweder .message oder .info einschließen, formatierte es sie nur mit Regeln, die sowohl .message als auch .info einschlossen.

Um die Definition von @extend klar und verständlich zu halten und die Implementierung sauber und effizient zu gestalten, ist dieses Verhalten nun veraltet und wird in zukünftigen Versionen entfernt.

Weitere Details finden Sie auf der Seite zu den breaking changes.

Nur einfache Selektoren – einzelne Selektoren wie .info oder a – können erweitert werden. Wenn .message.info erweitert werden könnte, besagt die Definition von @extend, dass Elemente, die dem Erweiterer entsprechen, so formatiert würden, als ob sie .message.info entsprechen würden. Das entspricht dem Abgleich von sowohl .message als auch .info, sodass es keinen Vorteil hätte, stattdessen @extend .message, .info zu schreiben.

Ebenso würde .main .info erweitern (fast) dasselbe bewirken wie das Erweitern von .info allein. Die subtilen Unterschiede sind die Verwirrung nicht wert, die entsteht, wenn es so aussieht, als ob es etwas Wesentlich anderes tut, daher ist dies auch nicht erlaubt .

Spielplatz

SCSS-Syntax

.alert {
  @extend .message.info;
  //      ^^^^^^^^^^^^^
  // Error: Write @extend .message, .info instead.

  @extend .main .info;
  //      ^^^^^^^^^^^
  // Error: write @extend .info instead.
}
Spielplatz

Sass-Syntax

.alert
  @extend .message.info
  //      ^^^^^^^^^^^^^
  // Error: Write @extend .message, .info instead.

  @extend .main .info
  //      ^^^^^^^^^^^
  // Error: write @extend .info instead.

HTML HeuristikenHTML Heuristiken Permalink

Wenn @extend komplexe Selektoren verschachtelt, generiert es nicht alle möglichen Kombinationen von Vorfahrenselektoren. Viele der Selektoren, die es generieren könnte, passen wahrscheinlich nicht zu echtem HTML, und ihre vollständige Generierung würde Stylesheets viel zu groß für sehr wenig echten Wert machen. Stattdessen verwendet es eine Heuristik: Es geht davon aus, dass die Vorfahren jedes Selektors in sich abgeschlossen sind, ohne mit den Vorfahren anderer Selektoren verschachtelt zu sein.

Spielplatz

SCSS-Syntax

header .warning li {
  font-weight: bold;
}

aside .notice dd {
  // Sass doesn't generate CSS to match the <dd> in
  //
  // <header>
  //   <aside>
  //     <div class="warning">
  //       <div class="notice">
  //         <dd>...</dd>
  //       </div>
  //     </div>
  //   </aside>
  // </header>
  //
  // because matching all elements like that would require us to generate nine
  // new selectors instead of just two.
  @extend li;
}
Spielplatz

Sass-Syntax

header .warning li
  font-weight: bold


aside .notice dd
  // Sass doesn't generate CSS to match the <dd> in
  //
  // <header>
  //   <aside>
  //     <div class="warning">
  //       <div class="notice">
  //         <dd>...</dd>
  //       </div>
  //     </div>
  //   </aside>
  // </header>
  //
  // because matching all elements like that would require us to generate nine
  // new selectors instead of just two.
  @extend li

CSS-Ausgabe

header .warning li, header .warning aside .notice dd, aside .notice header .warning dd {
  font-weight: bold;
}


















Erweitern in @mediaErweitern in @media Permalink

Obwohl @extend innerhalb von @media und anderen CSS-At-Regeln erlaubt ist, dürfen keine Selektoren erweitert werden, die außerhalb ihrer At-Regel erscheinen. Dies liegt daran, dass der erweiternde Selektor nur innerhalb des gegebenen Medienkontextes gilt und es keine Möglichkeit gibt, sicherzustellen, dass diese Einschränkung im generierten Selektor erhalten bleibt, ohne die gesamte Stilregel zu duplizieren.

Spielplatz

SCSS-Syntax

@media screen and (max-width: 600px) {
  .error--serious {
    @extend .error;
    //      ^^^^^^
    // Error: ".error" was extended in @media, but used outside it.
  }
}

.error {
  border: 1px #f00;
  background-color: #fdd;
}
Spielplatz

Sass-Syntax

@media screen and (max-width: 600px)
  .error--serious
    @extend .error
    //      ^^^^^^
    // Error: ".error" was extended in @media, but used outside it.



.error
  border: 1px #f00
  background-color: #fdd