SASS Schnellstart – Extend Directive
Wie wir gesehen haben, sind Mixins eine Möglichkeit, mit einigen Situationen umzugehen, ohne Code doppelt zu schreiben. Aber Sass bietet noch einen anderen Weg, nämlich das @extend Directive. Das Extend-Directive ermöglich eine Art Vererbung, indem es einem Style erlaubt, einen anderen einzuschließen.
Vererbung mit @extend
Anders als bei Mixins, musst du eine Erweiterung nicht explizit deklarieren. Du kannst jede Klassenregel mit den Regeln anderer Klassen erweitern, indem du einfach die @extend Direktive dort einfügst, wo du die Klassen einschließen möchtest. Hier ist ein Beispiel.
.button-base {
radius: 2px;
margin: 5px;
}
.menu-button {
@extend .button-base;
background-color: blue;
color: white;
}
.button-base,
.menu-button {
radius: 2px;
margin: 5px;
}
.menu-button {
background-color: blue;
color: white;
}
Jetzt musst du nur noch .menu-button als Klasse angeben, um beide Stile zu übernehmen. Wie bei Mixins erspart dir die Verwendung das @extend-Directive auf diese Weise die Mühe, etwas wie folgt in dein HTML zu schreiben, was langatmig und schwerer zu lesen ist: <a class=".button-base .menu-button">Mein Button</a>
Vererbungsverkettung
Wie bei jeder objektorientierten Programmiersprache kann das @extend Directive verkettet werden. Das heißt, du kannst eine Klasse erweitern, die eine andere Klasse erweitert:
.button-base {
margin: 2px;
radius: 2px;
}
.error-button {
@extend .button-base;
background-color: red;
}
.menu-button-error {
@extend .error-button;
}
CSS:
.button-base,
.error-button,
.menu-button-error {
margin: 2px;
radius: 2px;
}
.error-button,
.menu-button-error {
background-color: red;
}
Mehrfach-Vererbung
Im Gegensatz zu den meisten objektorientierten Programmiersprachen, die nur die Vererbung von einer einzigen Basisklasse erlauben, kannst du @extend für so viele verschiedene Klassen wie nötig verwenden:
.button-base {
margin: 2px;
radius: 2px;
}
.error-base {
background-color: red;
}
.error-button {
@extend .button-base;
@extend .error-base;
}
Beachte, dass es nicht notwendig ist, dass die Kindklasse irgendwelche eigenen Eigenschaften enthält. Das obige Beispiel resultiert in folgendem CSS:
.button-base,
.error-button {
margin: 2px;
radius: 2px;
}
.error-base,
.error-button {
background-color: red;
}
Sonstige Selektoren erweitern
Nur einzelne Selektoren können erweitert werden. Du kannst z.B. nicht p.test erweitern. Aber du kannst das @extend Directive verwenden, um Stile von jedem einzelnen Selektor zu erben, egal wie komplex. Selektoren wie p.error und Pseudo-Klassen wie :first-child funktionieren genauso gut. Die Syntax ist die gleiche.
li:first-child {
color: red;
}
.link-liste {
@extend li:first-child;
}
CSS:
li:first-child,
.link-liste {
color: red;
}
Ist dir aufgefallen, dass in allen obigen Beispielen die Basisklasse, also die Klasse, die mit der @extend Direktive aufgerufen wird, im resultierenden CSS enthalten ist? Das ist anders als das Verhalten oder die Mixins, die nur ausgegeben werden, wenn sie mit der @include Direktive aufgerufen werden.
Sass bietet einen Mechanismus, um die Basisklasse von der Ausgabe auszuschließen, und zwar über den Platzhalterselektor, %. Füge einfach ein %-Symbol vor dem Namen des Selektors ein und er wird nicht in der Ausgabe enthalten sein:
%button-base {
margin: 2px;
radius: 2px;
}
.error-button {
@extend %button-base;
background-color: red;
}
.error-button {
margin: 2px;
radius: 2px;
}
.error-button {
background-color: red;
}
Natürlich ist dies nicht das effizienteste CSS, da der .error-button Selektor zweimal verwendet wird. Aber das Beispiel ist genau das, ein Beispiel. In einem echten Projekt würde es wahrscheinlich keinen Sinn machen, den Platzhalter zu deklarieren, es sei denn, du würdest ihn mehr als einmal verwenden.
@extend innerhalb von Directives verwenden
Die aktuelle Version des Sass-Compilers kann Klassen innerhalb von Direktiven wie @media nicht effizient erweitern, es sei denn, die Basisklasse befindet sich ebenfalls innerhalb der Directives. Du kannst jedoch Klassen innerhalb des Kontextes des Directives referenzieren, also funktioniert das gut:
@media print {
.text {
font-family: Sans Serif;
}
p {
@extend .text;
farbe: blue;
}
}
CSS:
@media print {
.text,
p {
font-family: Sans Serif;
}
p {
color: blue;
}
}
Extend vs. Mixins
In letzter Zeit gab es in der Sass-Community eine große Debatte über die Wahl von Mixins gegenüber des @extend-Directives, und letztere wurde ein wenig "verprügelt".
Die Funktionalität der @extend Directive und der Sass-Mixins ist dabei sehr ähnlich. Tatsächlich kannst du mit @extend nichts machen, was du nicht auch mit einem Mixin tun kannst, und @extend unterstützt weder Variablen, noch kann es innerhalb von @media Direktiven verwendet werden. Warum solltest du es also benutzen?
Ein Grund für @extend ist, dass es ein kompakteres CSS erzeugt. Ein Mixin kopiert seine Regeln in jeden Style, der es beinhaltet. Die Verwendung von @extend passt die Selektoren so an, dass jede gegebene Regel nur einmal enthalten ist. Auf der anderen Seite neigen Mixins dazu, zu einer kleineren Größe zu komprimieren, wenn sie gzip verwenden.
Letztendlich kommt es wahrscheinlich darauf an, wie du über das Coding denkst. Erinnere dich daran, dass Sass existiert, um das Schreiben von CSS effizienter und wartbarer zu machen. Wenn du von einem objektorientierten Hintergrund kommst, wird die Verwendung von @extend zum Erstellen von Vererbungsbeziehungen ein komfortables Muster für dich sein. In den meisten Situationen ist die Reduzierung der Entwicklungszeit ein paar zusätzliche Bytes CSS wert.
Wenn dir die ganze objektorientierte Sache ein Rätsel ist, wirst du dich vielleicht mit Mixins wohler fühlen, und du kannst sicher sein, dass dein CSS etwas kleiner sein wird. Es gibt (zum Glück) keine Code-Polizei. Es liegt an dir, zu entscheiden, was für ein Styling-Problem in einem bestimmten Projekt besser funktioniert.