Sass'ta dinamik olarak değişkenler oluşturma veya bunlara referans verme


94

Başka bir değişkene başvurmak için değişkenimde dize enterpolasyonu kullanmaya çalışıyorum:

// 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');

Ancak bunu yaptığımda şu hatayı alıyorum:

Tanımsız değişken: "$ foo-".

Sass, PHP tarzı değişken değişkenleri destekliyor mu?

Yanıtlar:


50

Sass, değişkenlerin dinamik olarak oluşturulmasına veya erişilmesine izin vermez. Ancak, benzer davranışlar için listeleri kullanabilirsiniz.

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 oluşturuldu:

#smth {
  width: 30px; 
}

9
@castus bu sorununuzu nasıl çözdü? Bir listeden bir dize değeri alıp ona bir $ eklemem ve onu bir değişken olarak kullanmam gereken çok benzer bir sorunla karşılaşıyorum.
cmegown

88

Bu aslında değişkenler yerine SASS haritalarını kullanarak yapmak mümkündür. İşte hızlı bir örnek:

Dinamik olarak referans verme:

$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);
}

Çıktıları:

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

Dinamik olarak oluşturmak:

@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); }
  }
}

Çıktıları:

a.blue { color: #007dc6; }
a.blue:hover { color: #3da1e0; }
a.red { color: red; }
a.red:hover { color: #cc0000; }

10
Bunun hala "dinamik değişkenler" olmadığını unutmayın. Bu, sonsuza dek kullandığımız bir liste listesini kullanmanın bir varyasyonudur.
cimmanon

13
Bu aslında, yalnızca belirleyici değişken olarak bir dizin numarasını kabul eden listelere genişler. Değişkenlerin, istenen işlevsellik olan geçirilen bir dizenin birleştirilmesiyle oluşturulan dinamik olarak oluşturulmuş bir adla çağrılmasına izin verir.
dibbledeedoo

3
Kabul edilen cevap bu olmalıdır. Tamamen dinamik olmasa da bu, istenen işlevselliği en iyi şekilde taklit eder.
thomaux

1
Yararlı olsa da, bu örnek hiç değişken oluşturmuyor
ithil

Doğru. Operasyonun sorusunun başlığına rağmen, metni değişkenlerin yaratılmasını tanımlamıyordu, bu yüzden buna değinmedim. Ancak, bunu yapmaya ilişkin bir bölüm ekledik (yine de haritalarla, tekil değişkenlerle değil).
dibbledeedoo

5

Koşullu bir değer kullanmam gerektiğinde, işlevlere güveniyorum. İşte basit bir örnek.

$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);
}

Sanırım tam da aradığım şey bu. Bu, esasen miksere aktarılan değeri almak ve onu işlev boyunca çalıştırmaktır. Ardından, bir dizi if ifadesine bağlı olarak, bir değişkenle aynı dize değerini döndürür. Bunu potansiyel olarak sonsuz sayıda değerle yapmak mümkün olabilir mi? Diyelim ki, sadece foo veya bar değil, birçok dizeden oluşan bir listemiz var.
cmegown

3
Bu tamamen kötü bir uygulamadır, sonsuz bir if koşulları zinciriyle sonuçlanmak istemezsiniz. Anahtar-değer çiftleri ile SASS haritalarını kullanın ve bunun yerine değerleri ondan çekin.
mystrdat

Bu vitrinde çoğunlukla gereksiz - neden sadece aramıyorsunuz @include do-this($foo);? ... ancak, işlev gerçekten bir şey yaptıysa, bu mantıklı olurdu, ancak yalnızca geçer ...
jave.web

2

Raylarla çalışıyorsanız ve muhtemelen başka koşullar altında başka bir seçenek.

Dosya uzantısının sonuna .erb eklerseniz, Rails dosyayı SASS yorumlayıcısına göndermeden önce dosyadaki erb'yi işler. Bu size Ruby'de istediğinizi yapma şansı verir.

Örneğin: (Dosya: 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') %>
}

Aşağıdaki scss'de sonuçlar:

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

#target {
  width: $foo-baz;
}

Hangisi, genel olarak aşağıdaki css ile sonuçlanır:

#target {
  width: 20px;
}

0

Son zamanlarda dinamik olarak bir renge başvurma ihtiyacıyla karşılaştım.

Her proje için bir _colours.scss dosyam var, burada tüm renklerimi bir kez tanımlıyorum ve bunları değişkenler olarak referans alıyorum.

_Forms.scss dosyamda, mevcut her renk için düğme stilleri ayarlamak istedim. Genellikle sıkıcı bir iştir. Bu, her farklı renk için aynı kodu yazmak zorunda kalmamama yardımcı oldu.

Tek dezavantajı, gerçek css'yi yazmadan önce her bir renk adını ve değerini listelemeniz gerektiğidir.

// $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%);
  }
}

-2

SASS komutunu çalıştırdığınızda bir kez ayrıştırılması gereken başka bir değişkeni ekleyeceğiniz / bağlayacağınız için, şu an itibariyle bir dinamik değişken yapmak mümkün değildir.

Komut çalışır çalışmaz Geçersiz CSS için bir hata atar, çünkü bildirilen tüm değişkenleriniz kaldırmayı takip eder.

Bir kez çalıştırdıktan sonra, değişkenleri anında yeniden tanımlayamazsınız

Bunu anladığımı bilmek için, lütfen aşağıdakilerin doğru olup olmadığını belirtin:

sonraki bölümün (kelimenin) dinamik olduğu değişkenleri bildirmek istiyorsunuz

gibi bir şey

$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
    }
}

İstediğin buysa korkarım şu an için buna izin yok


3
Maalesef bu işe yaramıyor: hata scss / components.scss (Satır 71: "$ font-" sonrasında geçersiz CSS: beklenen ":", "$ n: normal $ n 1 ..." idi)
Krzysztof Romanowski

4
@castus, oops! net olmadığım için özür dilerim - bir çözüm vermiyorum, soruyu bir kez daha açıklamak yerine
Om Shankar

16
Muhtemelen izin verilmeyen bir çözüm göndermemelisiniz!
Rhyso

Bu işe yarayacak ama sass aracılığıyla değişken oluşturamıyoruz gibi görünüyor?
v3nt
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.