Skip to main content
F-LOG-GE

Mixins für Sass können ausufern

Das Tolle an Präprozessoren wie Sass ist, dass man Problemlösungen abstrahieren kann. Man entwickelt dann für Sass (meinen bevorzugten Präprozessor) Mixins oder Placeholder und greift während seiner Projekte immer wieder darauf zu.

Mir macht es sehr viel Spaß, an Sass-Mixins zu arbeiten. Allerdings muss ich mich zunehmend zügeln, denn schliesslich sollen Aufwand und Nutzen in einem vernünftigen Verhältnis stehen. Den schmalen Grat dazwischen kann ich sehr schön anhand meiner unterschiedlichen Mixins zur Erstellung von Dreiecken mittels CSS verdeutlichen.

Für manche wird es neu sein (das ist meine Erfahrung in Schulungen), aber ich hoffe, die meisten Leser wissen, dass man mittels der border-Eigenschaft ein Dreieck erzeugen kann. Dies nun mit generiertem Content kombiniert ermöglicht uns den Verzicht auf kleine Grafiken. Eine typische Lösung sähe beispielsweise so aus:

.arrow {
    position: relative;
    /* variabler Teil */
    padding-left: 20px;
}
.arrow:before {
    content: "";
    display: block;
    width: 0;
    height: 0;
    position: absolute;
    /* variabler Teil */
    left: 0;
    top: 3px;
    border: 6px solid transparent;
    border-left-color: #000;
}

Ich habe bei dem kurzen Testcode den variablen Bestandteil markiert. Der Anteil an quasi unverrückbarem Code ist recht umfangreich. Es lohnt sich also, ihn auszulagern. Die variablen Teile kann man nun immer individuell notieren oder aber dies ein Mixin erledigen lassen.

Ein Aspekt macht die Sache komplexer, als es auf den ersten Blick aussieht: im Beispiel habe ich mittels :before ein Dreick am linken Rand erzeugt. Das muss nicht immer das gewünschte Ergebnis sein. Der Pfeil kann in eine andere Richtung weisen, er kann auch erst am Ende des markierten Elements erscheinen.

Die Lösung muss also flexibel genug sein, auch für “:after” zu gelten, anstatt left auch right zuzulassen und eine andere Border sichtbar zu machen.

Mein erstes Mixin für dieses Designdetail sah folgendermassen aus:

@mixin b-a($ba: before, $border-width: 6px) {
    $seladd : ":";
    &{position: relative;}
    &#{$seladd+$ba} {
        content: ""; 
        display: block; 
        width: 0; 
        height: 0; 
        border: $border-width solid transparent; 
        position: absolute; 
    }
}

Und es wurde folgendermassen aufgerufen:

.arrow {
    @include b-a();
    padding-left: 20px;
  &:before {
      border-left-color: #000;
      top: 3px;
  }
}

Die oben skizzierte Version ist die Standardvariante des Mixins. Möchte ich nun anstatt :before lieber das Pseudoelement :after nutzen, rufe ich das Mixin entsprechend auf:

.arrow{
    @include b-a(after);
    padding-left: 20px;
    &:after {
      border-left-color: #000;
      top: 3px;
    }
}

Standardwerte bleiben von links nach rechts gelesen erhalten. Dabei kann man leider keine Standardwerte überspringen. Möchte ich also nur die Größe des Pfeils ändern, die Voreinstellung before aber belassen, so muss ich trotzdem before eintragen. Sass kann nicht wissen, dass “10px” für den zweiten und nicht für den ersten Wert gedacht sind.

Der Charme des vorgestellten Mixins liegt meiner Ansicht nach darin, dass ich nur zwei Werte verändern kann und alle weiteren Eigenschaften individuell hinzufügen muss. Der Code wird dadurch in meinen Augen lesbar bleiben.

Mein Ehrgeiz trieb mich allerdings so weit, ein noch ausgefeilteres Mixin zu schreiben. Es würde die ganze Angelegenheit auf eine Zeile reduzieren. Allerdings emfpinde ich das Mixin nicht mehr intuitiv handhabbar. Dementsprechend benannte ich das Mixin b-a-complex:

@mixin b-a-complex($ba: before, $border-color: #000, $border-width: 6px, $padding: 20px, $border-side: left, $top-position: 3px, $position-side: $border-side, $position-side-distance: 0) {
    $seladd : ":";
    position: relative;
    padding-#{$border-side}: $padding;
    &#{$seladd+$ba} {
        content: ""; 
        display: block; 
        width: 0; height: 0; 
        border: $border-width solid transparent; 
        border-#{$border-side}-color: $border-color;
        position: absolute;
        top: $top-position;
        #{$position-side}: $position-side-distance; 
    }
}

Die ganze Arbeit hat sich somit auf nur eine Zeile reduziert:

.arrow {
    @include b-a-complex();
}

Allerdings haben wir nun zwei Probleme:

  1. Wir müssen uns alle Variablen in der korrekten Reihenfolge und mit ihren Standardwerten merken. Realistischerweise müssen wir dafür immer in den Code des Mixins schauen.
  2. Bei der Erstellung des Mixins müssen wir erahnen, welche Variablen häufiger geändert werden, als andere. Denn diese müssen in der Reihenfolge nach vorne wandern.

Ein solches Mixin ist eine gute Übung, aber praktisch nutzbar ist es nicht. Das erste Mixin hingegen nutze ich recht gerne. Es nimmt mir immer wiederkehrende Arbeit ab.

Dies ist ein Archiv meines alten Weblogs, das von Oktober 2006 bis Dezember 2022 als Wordpress-Instanz existierte.