Membuat atau mereferensikan variabel secara dinamis di Sass

94

Saya mencoba menggunakan interpolasi string pada variabel saya untuk mereferensikan variabel lain:

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

Tetapi ketika saya melakukan ini, saya mendapatkan kesalahan berikut:

Variabel tidak ditentukan: "$ foo-".

Apakah Sass mendukung variabel variabel gaya PHP?

Krzysztof Romanowski
sumber

Jawaban:

50

Sass tidak mengizinkan variabel dibuat atau diakses secara dinamis. Namun, Anda dapat menggunakan daftar untuk perilaku serupa.

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 dihasilkan:

#smth {
  width: 30px; 
}
lisowski.r
sumber
9
@castus bagaimana ini memecahkan masalah Anda? Saya mengalami masalah yang sangat mirip di mana saya perlu mengambil nilai string dari daftar dan menambahkan $ ke dalamnya dan menggunakannya sebagai variabel.
cmegown
88

Ini sebenarnya dapat dilakukan dengan menggunakan peta SASS daripada variabel. Berikut contoh singkatnya:

Merujuk secara dinamis:

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

Dihasilkan sebagai:

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

Membuat secara dinamis:

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

Dihasilkan sebagai:

a.blue { color: #007dc6; }
a.blue:hover { color: #3da1e0; }
a.red { color: red; }
a.red:hover { color: #cc0000; }
dibbledeedoo
sumber
10
Perhatikan bahwa ini masih bukan "variabel dinamis". Ini hanyalah variasi dalam menggunakan daftar daftar yang telah kami gunakan sejak lama.
cimmanon
13
Ini sebenarnya memperluas daftar, yang hanya menerima nomor indeks sebagai variabel penentu. Ini memungkinkan variabel dipanggil dengan nama yang dihasilkan secara dinamis, dibuat dengan penggabungan string yang diteruskan, yang merupakan fungsionalitas yang diminta.
dibbledeedoo
3
Ini harus menjadi jawaban yang diterima. Meskipun tidak sepenuhnya dinamis, ini paling baik meniru fungsionalitas yang diminta.
thomaux
1
Meskipun berguna, contoh ini tidak membuat variabel sama sekali
sampai
Benar. Terlepas dari judul pertanyaan op, teksnya tidak menjelaskan pembuatan variabel, jadi saya tidak membahasnya. Namun, hanya menambahkan bagian relatif untuk melakukan itu (meskipun masih dengan peta, bukan variabel tunggal).
dibbledeedoo
5

Kapan pun saya perlu menggunakan nilai bersyarat, saya mengandalkan fungsi. Berikut contoh sederhananya.

$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
sumber
Saya pikir inilah yang saya cari. Ini pada dasarnya mengambil nilai yang diteruskan ke mixin dan menjalankannya melalui fungsi. Kemudian, bergantung pada serangkaian pernyataan if, mengembalikan nilai string yang sama sebagai variabel. Apakah mungkin melakukan ini dengan jumlah nilai yang berpotensi tak terbatas? Katakanlah kita memiliki daftar banyak string, bukan hanya foo atau bar.
cmegown
3
Ini murni praktik buruk, Anda tidak ingin berakhir dengan rantai kondisi if yang tak ada habisnya. Gunakan peta SASS dengan pasangan nilai kunci dan tarik nilai darinya.
mystrdat
Ini terutama berlebihan dalam etalase ini - mengapa Anda tidak menelepon saja @include do-this($foo);? ... bagaimanapun ini akan masuk akal, jika fungsinya benar-benar melakukan sesuatu, tetapi hanya lewat ...
jave.
2

Berikut opsi lain jika Anda bekerja dengan rel, dan mungkin dalam keadaan lain.

Jika Anda menambahkan .erb di akhir ekstensi file, Rails akan memproses erb pada file tersebut sebelum mengirimkannya ke juru bahasa SASS. Ini memberi Anda kesempatan untuk melakukan apa yang Anda inginkan di Ruby.

Misalnya: (File: 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') %>
}

Hasil di scss berikut:

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

#target {
  width: $foo-baz;
}

Yang mana, dari kasar, menghasilkan css berikut:

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

Saya menemukan kebutuhan untuk mereferensikan warna secara dinamis baru-baru ini.

Saya memiliki file _colours.scss untuk setiap proyek, di mana saya mendefinisikan semua warna saya sekali dan mereferensikannya sebagai variabel.

Dalam file _forms.scss saya, saya ingin mengatur gaya tombol untuk setiap warna yang tersedia. Biasanya tugas yang membosankan. Ini membantu saya menghindari keharusan menulis kode yang sama untuk setiap warna yang berbeda.

Satu-satunya downside adalah Anda harus membuat daftar setiap nama warna dan nilai sebelum menulis css yang sebenarnya.

// $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
sumber
-2

Untuk membuat variabel dinamis tidak dimungkinkan di SASS seperti sekarang, karena Anda akan menambahkan / menghubungkan var lain yang perlu diurai sekali saat Anda menjalankan perintah sass.

Segera setelah perintah dijalankan, itu akan memunculkan kesalahan untuk CSS tidak valid, karena semua variabel yang Anda deklarasikan akan mengikuti pengangkatan.

Setelah dijalankan, Anda tidak dapat mendeklarasikan variabel lagi dengan cepat

Untuk mengetahui bahwa saya telah memahami ini, mohon nyatakan jika yang berikut ini benar:

Anda ingin mendeklarasikan variabel di mana bagian berikutnya (kata) dinamis

sesuatu seperti

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

Jika ini yang Anda inginkan, saya khawatir sekarang, ini tidak diperbolehkan

Om Shankar
sumber
3
Sayangnya ini tidak berfungsi: error scss / components.scss (Baris 71: CSS tidak valid setelah "$ font-": diharapkan ":", sebelumnya "$ n: normal $ n 1 ...")
Krzysztof Romanowski
4
@castus, oops! maaf karena tidak jelas - saya tidak memberikan solusi, melainkan menjelaskan pertanyaannya sekali lagi
Om Shankar
16
mungkin sebaiknya tidak memposting solusi yang tidak diperbolehkan!
Rhyso
i width ini akan berfungsi tetapi tampaknya kita tidak dapat membuat variabel melalui sass?
v3nt