Динамічне створення або посилання на змінні в Sass


94

Я намагаюся використовувати інтерполяцію рядків для своєї змінної для посилання на іншу змінну:

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

Але коли я роблю це, я отримую таку помилку:

Невизначена змінна: "$ foo-".

Чи підтримує Sass змінні змінні у стилі PHP?

Відповіді:


50

Sass не дозволяє створювати змінні або отримувати динамічний доступ до них. Однак ви можете використовувати списки для подібної поведінки.

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 згенеровано:

#smth {
  width: 30px; 
}

9
@castus, як це вирішило вашу проблему? Я стикаюся з дуже подібною проблемою, коли мені потрібно взяти зі списку значення рядка, додати до нього $ і використовувати його як змінну.
cmegown,

88

Це насправді можна зробити, використовуючи карти SASS замість змінних. Ось короткий приклад:

Динамічне посилання:

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

Виводиться як:

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

Динамічне створення:

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

Виводиться як:

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

10
Зверніть увагу, що це все ще не "динамічні змінні". Це лише варіація використання списку списків, які ми використовуємо з тих пір.
cimmanon

13
Це фактично розширюється на списки, які приймають лише номер індексу як специфічну змінну. Це дозволяє викликати змінні з динамічно генерованим ім'ям, створеним шляхом об'єднання переданого рядка, який був запитуваною функціональністю.
dibbledeedoo

3
Це має бути прийнятою відповіддю. Хоча це не повністю динамічно, це найкраще імітує необхідну функціональність.
thomaux 02

1
Цей приклад, хоча і корисний, взагалі не створює жодних змінних
до

Правда. Незважаючи на заголовок запитання, його текст не описував створення змінних, тому я не звертався до цього. Однак щойно додав розділ, що стосується цього (хоча, все-таки з картами, а не окремими змінними).
dibbledeedoo

5

Кожного разу, коли мені потрібно використовувати умовне значення, я спираюся на функції. Ось простий приклад.

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

Я думаю, це саме те, що я шукаю. Це, по суті, приймає значення, передане міксіну, і запускає його через функцію. Потім, залежно від серії операторів if, повертає те саме значення рядка, що і змінна. Чи можна це зробити з потенційно нескінченною кількістю значень? Скажімо, у нас є список багатьох рядків, а не лише foo або bar.
cmegown,

3
Це чисто погана практика, ви не хочете, щоб у кінцевому підсумку з’явився нескінченний ланцюг ситуацій if. Використовуйте карти SASS з парами ключових значень і натомість витягуйте з них значення.
mystrdat

Це в основному зайве у цій вітрині - чому б вам не зателефонувати просто @include do-this($foo);? ... однак це мало б сенс, якби функція насправді щось робила, але вона лише передає ...
jave.web

2

Ось ще один варіант, якщо ви працюєте з рейками, і, можливо, за інших обставин.

Якщо ви додасте .erb до кінця розширення файлу, Rails обробить erb у файлі, перш ніж відправити його інтерпретатору SASS. Це дає вам можливість зробити те, що ви хочете, у Ruby.

Наприклад: (Файл: 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') %>
}

Результати:

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

#target {
  width: $foo-baz;
}

Що, грубо кажучи, призводить до наступного css:

#target {
  width: 20px;
}

0

Нещодавно я натрапив на необхідність динамічного посилання на колір.

У мене є файл _colours.scss для кожного проекту, де я визначаю всі свої кольори один раз і посилаюся на них як на змінні.

У своєму файлі _forms.scss я хотів встановити стилі кнопок для кожного доступного кольору. Зазвичай це нудне завдання. Це допомогло мені уникнути необхідності писати однаковий код для кожного іншого кольору.

Єдиним недоліком є ​​те, що перед написанням фактичного css вам потрібно перерахувати кожне ім’я та значення кольору.

// $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 неможливо, оскільки ви будете додавати / підключати іншу змінну, яку потрібно проаналізувати один раз під час запуску команди sass.

Як тільки команда запуститься, вона видасть помилку для недійсного CSS, оскільки всі ваші оголошені змінні будуть слідувати за підняттям.

Після запуску ви не можете повторно оголошувати змінні на льоту

Щоб знати, що я це зрозумів, будь ласка, зазначте, якщо правильно вказано наступне:

ви хочете оголосити змінні, де наступна частина (слово) є динамічною

щось на зразок

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

Якщо це те, що ви хочете, я боюся, що зараз це заборонено


3
На жаль, це не працює: помилка scss / components.scss (рядок 71: Недійсний CSS після "$ font-": очікувано ":", був "$ n: нормальний $ n 1 ...")
Кшиштоф Романовський,

4
@castus, ой! вибачте за незрозумілість - я не даю рішення, а ще раз
пояснюю

16
мабуть, не слід розміщувати рішення, яке заборонено!
Rhyso

Я ширина це буде працювати, але, здається, ми не можемо створювати змінні через sass?
v3nt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.