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... */
}
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