Dynamisches Erstellen oder Referenzieren von Variablen in Sass

91

Ich versuche, die Zeichenfolgeninterpolation für meine Variable zu verwenden, um auf eine andere Variable zu verweisen:

// Set up variable and mixin
$foo-baz: 20px;

@mixin do-this($bar) {
    width: $foo-#{$bar};
}

// Use mixin by passing 'baz' string as a param for use $foo-baz variable in the mixin
@include do-this('baz');

Aber wenn ich das mache, bekomme ich folgenden Fehler:

Undefinierte Variable: "$ foo-".

Unterstützt Sass Variablenvariablen im PHP-Stil?

Krzysztof Romanowski
quelle

Antworten:

49

Mit Sass können keine Variablen dynamisch erstellt oder auf sie zugegriffen werden. Sie können jedoch Listen für ein ähnliches Verhalten verwenden.

scss:

$list: 20px 30px 40px;    
@mixin get-from-list($index) {
  width: nth($list, $index);
}

$item-number: 2;
#smth {
  @include get-from-list($item-number);
}

CSS generiert:

#smth {
  width: 30px; 
}
lisowski.r
quelle
9
@castus wie hat das dein problem gelöst? Ich stoße auf ein sehr ähnliches Problem, bei dem ich einen Zeichenfolgenwert aus einer Liste entnehmen und ein $ hinzufügen und als Variable verwenden muss.
cmegown
86

Dies ist tatsächlich mit SASS-Maps anstelle von Variablen möglich. Hier ist ein kurzes Beispiel:

Dynamisch referenzieren:

$colors: (
  blue: #007dc6,
  blue-hover: #3da1e0
);

@mixin colorSet($colorName) {
    color: map-get($colors, $colorName);
    &:hover {
        color: map-get($colors, $colorName#{-hover});
    }
}
a {
    @include colorSet(blue);
}

Ausgaben als:

a { color:#007dc6 }
a:hover { color:#3da1e0 }

Dynamisch erstellen:

@function addColorSet($colorName, $colorValue, $colorHoverValue: null) {
  $colorHoverValue: if($colorHoverValue == null, darken( $colorValue, 10% ), $colorHoverValue);

  $colors: map-merge($colors, (
    $colorName: $colorValue,
    $colorName#{-hover}: $colorHoverValue
  ));

  @return $colors;
}

@each $color in blue, red {
  @if not map-has-key($colors, $color) {
    $colors: addColorSet($color, $color);
  }
  a {
    &.#{$color} { @include colorSet($color); }
  }
}

Ausgaben als:

a.blue { color: #007dc6; }
a.blue:hover { color: #3da1e0; }
a.red { color: red; }
a.red:hover { color: #cc0000; }
dibbledeedoo
quelle
9
Beachten Sie, dass dies immer noch keine "dynamischen Variablen" sind. Dies ist nur eine Variation der Verwendung einer Liste von Listen, die wir seit Ewigkeiten verwenden.
Cimmanon
12
Dies erweitert tatsächlich Listen, die nur eine Indexnummer als spezifizierende Variable akzeptieren. Es ermöglicht den Aufruf der Variablen mit einem dynamisch generierten Namen, der durch Verkettung einer übergebenen Zeichenfolge erstellt wurde. Dies war die angeforderte Funktionalität.
Dibbledeedoo
3
Dies sollte die akzeptierte Antwort sein. Obwohl nicht vollständig dynamisch, ahmt dies die angeforderte Funktionalität am besten nach.
Thomaux
1
Dieses Beispiel ist zwar nützlich, erstellt jedoch überhaupt keine Variablen
bis zum
Wahr. Trotz des Titels der Frage der Operation wurde in ihrem Text die Erstellung von Variablen nicht beschrieben, daher habe ich mich nicht damit befasst. Es wurde jedoch nur ein Abschnitt dazu hinzugefügt (allerdings immer noch mit Karten, nicht mit singulären Variablen).
Dibbledeedoo
5

Immer wenn ich einen bedingten Wert verwenden muss, stütze ich mich auf Funktionen. Hier ist ein einfaches Beispiel.

$foo: 2em;
$bar: 1.5em;

@function foo-or-bar($value) {
  @if $value == "foo" {
    @return $foo;
  }
  @else {
    @return $bar;
  }
}

@mixin do-this($thing) {
  width: foo-or-bar($thing);
}
Adam Stacoviak
quelle
Ich denke, das ist genau das, wonach ich suche. Dies bedeutet im Wesentlichen, dass der an das Mixin übergebene Wert durch die Funktion ausgeführt wird. Gibt dann abhängig von einer Reihe von if-Anweisungen denselben Zeichenfolgenwert wie eine Variable zurück. Wäre es möglich, dies mit einer möglicherweise unendlichen Anzahl von Werten zu tun? Nehmen wir an, wir haben eine Liste mit vielen Zeichenfolgen, nicht nur foo oder bar.
cmegown
3
Dies ist eine reine schlechte Praxis. Sie möchten nicht mit einer endlosen Kette von Wenn-Bedingungen enden. Verwenden Sie SASS-Maps mit Schlüsselwertpaaren und ziehen Sie stattdessen die Werte daraus.
Mystrdat
In diesem Schaufenster ist es hauptsächlich überflüssig - warum würden Sie nicht einfach anrufen @include do-this($foo);? ... aber das wäre sinnvoll, wenn die Funktion tatsächlich etwas getan hätte, aber es geht nur vorbei ...
jave.web
2

Hier ist eine weitere Option, wenn Sie mit Schienen arbeiten und möglicherweise unter anderen Umständen.

Wenn Sie am Ende der Dateierweiterung .erb hinzufügen, verarbeitet Rails erb für die Datei, bevor sie an den SASS-Interpreter gesendet wird. Dies gibt Ihnen die Möglichkeit, in Ruby das zu tun, was Sie wollen.

Zum Beispiel: (Datei: foo.css.scss.erb)

// Set up variable and mixin
$foo-baz: 20px; // variable

<%
def do_this(bar)
  "width: $foo-#{bar};"
end
%>

#target {
  <%= do_this('baz') %>
}

Ergebnisse in folgenden scss:

// Set up variable and mixin
$foo-baz: 20px; // variable

#target {
  width: $foo-baz;
}

Was grob gesagt zu folgendem CSS führt:

#target {
  width: 20px;
}
Blake Taylor
quelle
0

Ich bin kürzlich auf die Notwendigkeit gestoßen, eine Farbe dynamisch zu referenzieren.

Ich habe für jedes Projekt eine _colours.scss-Datei, in der ich alle meine Farben einmal definiere und sie durchgehend als Variablen referenziere.

In meiner Datei _forms.scss wollte ich Schaltflächenstile für jede verfügbare Farbe einrichten. Normalerweise eine mühsame Aufgabe. Dies half mir zu vermeiden, dass ich für jede Farbe den gleichen Code schreiben musste.

Der einzige Nachteil ist, dass Sie jeden Farbnamen und Wert auflisten müssen, bevor Sie das eigentliche CSS schreiben.

// $red, $blue - variables defined in _colours.scss
$colours: 
  'red' $red,
  'blue' $blue;

@each $name, $colour in $colours {
  .button.has-#{$name}-background-color:hover {
    background-color: lighten($colour, 15%);
  }
}
lukeseager
quelle
-2

Das Erstellen einer dynamischen Variablen ist in SASS derzeit nicht möglich, da Sie eine weitere Variable hinzufügen / verbinden, die beim Ausführen des Befehls sass einmal analysiert werden muss.

Sobald der Befehl ausgeführt wird, wird ein Fehler für ungültiges CSS ausgegeben, da alle deklarierten Variablen dem Heben folgen.

Einmal ausgeführt, können Sie Variablen nicht mehr im laufenden Betrieb erneut deklarieren

Um zu wissen, dass ich dies verstanden habe, geben Sie bitte an, ob Folgendes korrekt ist:

Sie möchten Variablen deklarieren, bei denen der nächste Teil (Wort) dynamisch ist

etwas wie

$list: 100 200 300;

@each $n in $list {
    $font-$n: normal $n 12px/1 Arial;
}

// should result in something like

$font-100: normal 100 12px/1 Arial;
$font-200: normal 200 12px/1 Arial;
$font-300: normal 300 12px/1 Arial;

// So that we can use it as follows when needed

.span {
    font: $font-200;
    p {
       font: $font-100
    }
}

Wenn Sie dies wünschen, befürchte ich, dass dies derzeit nicht zulässig ist

Om Shankar
quelle
3
Leider funktioniert dies nicht: Fehler scss / components.scss (Zeile 71: Ungültiges CSS nach "$ font-": erwartet ":", war "$ n: normal $ n 1 ...")
Krzysztof Romanowski
4
@castus, oops! Es tut mir leid, dass ich nicht klar bin - ich gebe keine Lösung, sondern erkläre die Frage noch einmal
Om Shankar
15
sollte wahrscheinlich keine Lösung posten, die nicht erlaubt ist!
Rhyso
i width das würde funktionieren, aber anscheinend können wir keine Variablen über sass erstellen?
v3nt