具有旧版浏览器后备的CSS变量

时间:2017-05-30 21:08:13

标签: css css3 sass css-variables

TL; DR:如何使用SCSS为旧版浏览器提供回退的CSS变量。

我试图理解这个article。在我看来,你必须已经是一个先进的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 个答案:

答案 0 :(得分:10)

更新: Postcss Custom properties可以做后备并且比以下代码更容易

第1步:声明scss变量

首先,我们想将一些变量放在$map中,我会使用颜色变量:

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

第2步:自动化css 4 var generation

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

root中发生的事情是:对于颜色 map 中的每个键和值,我们打印以下内容:

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

我们重新创建了在@each循环

中生成var所做的工作

整个代码将是:

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

现在,这是文章中所做内容的简化。你应该检查它以使代码更健壮。

答案 1 :(得分:8)

如果你正在使用Sass,你可以通过Sass mixin自动化回退。创建CSS变量名称及其值的映射,然后您可以在mixin中查找这些值,这些值将输出回退样式和首选样式

$vars: (
  primary: yellow,
);

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

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

上面的mixin就像这样使用:

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

并输出以下CSS:

:root {
  --primary: yellow;
}

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

Etvoilà:)

答案 2 :(得分:1)

我认为你知道它没有显示后备的原因。但由于这是一个答案,我将解释原因

当前的mixin块只有一个background属性,这使得sass编译器只生成一个属性。我不认为sass可以确定是否' var'浏览器是否支持。因此,我们必须明确指出是否需要回退。

由于您已经拥有了地图,所以您只需通过提供密钥'主要'

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

这会将背景:黄色添加到body类中。或者,如果要根据条件控制后备的添加。你可以这样做

@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

注意:我正在编写答案,假设您只需要背景颜色,而不是该帖子中提到的所有其他属性。为此,您需要创建适当的数据结构