@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.
SCSS-Syntax
.error {
border: 1px #f00;
background-color: #fdd;
&--serious {
@extend .error;
border-width: 3px;
}
}
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.
SCSS-Syntax
.error:hover {
background-color: #fee;
}
.error--serious {
@extend .error;
border-width: 3px;
}
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#footergeneriert, 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.
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;
}
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.
SCSS-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
- 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 .
SCSS-Syntax
.alert {
@extend .message.info;
// ^^^^^^^^^^^^^
// Error: Write @extend .message, .info instead.
@extend .main .info;
// ^^^^^^^^^^^
// Error: write @extend .info instead.
}
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.
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;
}
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.
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;
}
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