CSS переменные с резервным вариантом для старых браузеров



TL; DR: как можно использовать SCSS, чтобы иметь переменные CSS с резервным вариантом для старых браузеров.



Я пытаюсь разобраться в этой статье . По моему мнению, вы уже должны быть продвинутым пользователем SASS, чтобы понять это, а я нет. Что еще хуже, это единственная статья, которую я нашел на эту тему.

Вот чего я пытаюсь добиться:



Мои scss должны быть примерно такими:



body {
@include v(background-color, primary)
}


Тогда обработанный CSS должен быть



body{
background: yellow; /* Yellow being defined above as the primary color */
background: var(--color-primary);
}


Поиграв немного, я уже могу получить значение переменной CSS следующим образом:



$colors: (
primary: yellow,
);

:root {
@each $name, $color in $colors {
--color-#{$name}: $color;
}
}

@mixin background-color($color_) {
background: var(--color-#{$color_});
}


Чтобы использовать его:



body{
@include background-color(primary);
}


Что приведет к следующему:



body {
background: var(--color-primary);
/* But the fallback is missing :(, I tried things with the map-get but it's really eluding me... */
}
623   3  

3 ответов:

Если вы используете Sass, вы можете автоматизировать резервные копии через Sass mixin. Создайте карту имен переменных CSS и их значений, а затем вы можете искать эти значения в микшине, которая выводит резервный стиль и предпочтительный

$vars: (
  primary: yellow,
);

:root {
  --primary: map-get($vars, primary);
}

@mixin var($property, $varName) {
  #{$property}: map-get($vars, $varName);
  #{$property}: var(--#{$varName});
}

Вышеуказанный миксин используется следующим образом:

body {
  @include var(background-color, primary);
}

И выводит следующий CSS:

:root {
  --primary: yellow;
}

body {
  background-color: yellow;
  background-color: var(--primary);
}

Et voilà :)

Обновление: пользовательские свойства Postcss могут выполнять резервное копирование и намного проще, чем приведенный ниже код

Шаг 1: объявить переменные scss

Итак, прежде всего мы хотим поместить некоторые переменные в $map, я пойду с переменными цвета:

$colors: (
  primary: #FFBB00,
  secondary: #0969A2
);

Шаг 2: автоматизируйте генерацию css 4 var

// ripped CSS4 vars out of color map
:root {
  // each item in color map
  @each $key, $value in $colors {
    --colors-#{$key}: $value;
  }
}

Что происходит в корне: для каждого ключа и значения в цветовой карте мы выводим следующее :

--colors-#{$key}: $value;

, что соответствует объявлениям переменных css. Я считаю, что странный бит с #{} вокруг ключа - это отсутствие пробелов вокруг значения. Таким образом, результат таков:

--colors-primary: #FFBB00,
--colors-secondary: #0969A2
Обратите внимание, что префикс (--colors-) является тем же именем, что и цветовая карта scss над ним. Почему - станет ясно в последнем шаге.

Шаг 3: много карт !

$props: (
  background-color: $colors
);

$map-maps: (
  background-color: colors
);

Здесь мы добавляем карту $props, которая сопоставляет свойство css с картой, содержащей значения. background-color Воля держите цвет, так что правильная карта $colors.

map-maps это копия реквизита, где вместо карты у нас есть название указанной карты. (это относится к примечанию в шаге 2).

Шаг 4: Давайте заставим его работать !

@mixin v($prop, $var) {
  // get the map from map name
  $map: map-get($props, $prop);
  // fallback value, grab the variable's value from the map
  $var-fall: map-get($map, $var);
  // our css4 variable output
  $var-output: var(--#{$map}-#{$var});    
  #{$prop}: $var-fall;
  // css4 variable output
  #{$prop}: $var-output;
}

body{
  @include v(background-color, primary);
}
Я немного упростил код в статье, он все еще работает, по крайней мере для этого примера, код в статье учитывает больше.

Во всяком случае, вот что происходит.

Во-первых, мы называем mixin с:

  @include v(background-color, primary);

Затем, войдя,

 $map: map-get($props, $prop); // map-get($props, background-color)

У нас есть переменная под названием $map, которой мы присваиваем значение, находящееся внутри карты $props в ключе background-color, который случайно является картой $colors. Это немного лабиринт, но он не так уж и сложен, как только вы его решите.

Тогда для запасного варианта:

 $var-fall: map-get($map, $var);

Это просто возвращает значение карты, которую мы только что получили (которая является $colors) в ключе $var (который оказывается первичным). Таким образом, результат является #FFBB00.

Для css var

  $map-name: map-get($map-maps, $prop);
  $var-output: var(--#{$map-name}-#{$var});

Мы воссоздаем то, что мы сделали для генерации var в цикле @each


Весь код будет выглядеть так:

$colors: (
  primary: #FFBB00,
  secondary: #0969A2
);

// ripped CSS4 vars out of color map
:root {
  // each item in color map
  @each $name, $color in $colors {
    --colors-#{$name}: $color;
  }
}



$props: (
  background-color: $colors,
  color:            $colors
);

$map-maps: (
  background-color: colors
);



@mixin v($prop, $var) {
  // get the map from map name
  $map: map-get($props, $prop);
  // fallback value, grab the variable's value from the map
  $var-fall: map-get($map, $var);
  // our css4 variable output

  $map-name: map-get($map-maps, $prop);
  $var-output: var(--#{$map-name}-#{$var});

  #{$prop}: $var-fall;
  // css4 variable output
  #{$prop}: $var-output;
}

body{
  @include v(background-color, primary);
}

Теперь это упрощение того, что сделано в статье. Вы должны проверить его, чтобы иметь код немного более надежным.

Я предполагаю, что вы знаете причину, по которой он не показал обратного хода. Но поскольку это ответ, я объясню причины

Текущий блок mixin имеет только одно фоновое свойство, которое заставляет компилятор sass генерировать только одно свойство. Я не думаю, что sass может определить, поддерживается ли 'var' в браузере или нет. Поэтому мы должны явно указать, нужен ли нам запасной вариант.

Поскольку у вас уже есть карта, все, что вам нужно, - это получить значение, дав ключ "первичный"

 @mixin background-color($color_) {
      background: var(--color-#{$color_});  
      background: map-get($colors, primary);
    }

Это добавит фон: желтый к классу тела всегда. Альтернативно, если вы хотите управлять добавлением запасного варианта на основе условия. Вы можете сделать вот так

@mixin background-color($color_, $showFall) {
  background: var(--color-#{$color_});  
  @if $showFall {
    background: map-get($colors, primary);
  }
}

И звоните вот так

body{
  @include background-color(primary, true);
}

Ручка кода для того же https://codepen.io/srajagop/pen/xdovON

Примечание: я пишу ответ в предположении, что вы хотите, чтобы работал только цвет фона, а не все другие свойства, подобные упомянутым в этом посте. Для этого вам нужно создать правильную структуру данных

Comments

    Ничего не найдено.