针对旧浏览器的具有回退功能的CSS变量

针对旧浏览器的具有回退功能的CSS变量,css,sass,css-variables,Css,Sass,Css Variables,TL;DR:如何使用SCS使CSS变量具有针对旧浏览器的回退功能 我想弄明白这一点。在我看来,你必须已经是一个高级SASS用户才能理解它,而我不是。更糟糕的是,这是我找到的唯一一篇关于这个主题的文章 以下是我努力实现的目标: 我的SCS应遵循以下原则: body { @include v(background-color, primary) } 然后处理的CSS应该 body{ background: yellow; /* Yellow being defined above as

TL;DR:如何使用SCS使CSS变量具有针对旧浏览器的回退功能

我想弄明白这一点。在我看来,你必须已经是一个高级SASS用户才能理解它,而我不是。更糟糕的是,这是我找到的唯一一篇关于这个主题的文章

以下是我努力实现的目标:

我的SCS应遵循以下原则:

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

我想你知道它没有显示回退的原因。但既然这是一个答案,我会解释原因

当前mixin块只有一个后台属性,这使得sass编译器只能生成一个属性。我认为sass无法确定浏览器中是否支持“var”。因此,我们必须明确指定是否需要回退

因为你已经有了地图,你所需要的只是通过给键'primary'来获得值

 @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);
}
像这样打电话

@mixin background-color($color_, $showFall) {
  background: var(--color-#{$color_});  
  @if $showFall {
    background: map-get($colors, primary);
  }
}
body{
  @include background-color(primary, true);
}
同样的代码笔

注意:我写这个答案的前提是,你只希望背景颜色起作用,而不是像那篇文章中提到的所有其他属性。为此,您需要创建适当的数据结构更新:可以进行回退,并且比下面的代码简单得多

步骤1:声明scss变量

// ripped CSS4 vars out of color map
:root {
  // each item in color map
  @each $key, $value in $colors {
    --colors-#{$key}: $value;
  }
}
首先,我们想在
$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;
  }
}
在root中发生的是:对于颜色映射中的每个键和值,我们打印以下内容:

--colors-#{$key}: $value;
它对应于css变量声明。我认为键周围有
{}
的奇怪之处在于值周围没有空格。 因此,结果是:

--colors-primary: #FFBB00,
--colors-secondary: #0969A2
请注意,前缀(
--colors-
)与其上方的scss颜色映射同名。原因将在最后一步中变得清楚


步骤3:大量地图

$props: (
  background-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
  $var-output: var(--#{$map}-#{$var});    
  #{$prop}: $var-fall;
  // css4 variable output
  #{$prop}: $var-output;
}

body{
  @include v(background-color, primary);
}
这里我们添加map
$props
,它将css属性映射到包含值的映射<代码>背景色将保留颜色,因此正确的贴图是
$colors

地图地图
是道具的副本,其中我们使用的不是地图,而是所述地图的名称。(这与步骤2中的注释有关)

第四步:让我们开始吧

$props: (
  background-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
  $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);
这只需在
$var
键(恰好是主键)处获取刚刚获得的映射值(即
$colors
)。因此,结果是
#FFBB00

对于cssvar

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


现在,这是本文所做工作的简化。您应该检查它,使代码更加健壮。

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

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

等一下:)

谢谢。事实上,我理解了为什么它没有显示出来,但是你的回答让我理解了整篇文章。因为我的问题是关于
@include v(背景色,原色)
,我觉得这对未来的读者有好处,所以我将通过解释他是如何做到的来回答这个问题。然而,如果你真的想这样做,我会接受你的答案,如果不是,我会接受我的答案。我今天的时间到了。请继续回答这个问题,好的解释。我的加号1确保将回退放在变量之前,否则将始终使用“回退”代替!这个答案会更好,因为他的答案也不必要的复杂,无论是在代码还是在解释的长度上。哇,不要在生产中使用这个。聪明但设计过度且不必要。总是喜欢可读性胜过魔术。几年后你会感谢我的。很好,顺便说一句,一些POSTSS插件会自动做到这一点(如果我没记错的话,它被称为自定义属性)。我最终使用了它,因为它更方便:你好,比利时人:)仅供参考,您需要插值map get,所以
--primary:#{map get($vars,primary)}这实际上比我的答案要好得多,我接受一年后的答案:对不起,如果每个
var
后面都跟有“浏览器兼容性”的文本值,那么使用变量的目的是什么?@caiosm1005该变量将在较新的浏览器上使用,因此当您使用VAR而没有回退时,该值与正常值相同。在开发时,也将使用变量,并且只有在编译时才会插入文本值。顺便说一句,后面不是文字值,文字值在前面,这就是重点(否则就没有用了)。是的,意思是在前面。我的错。不过,如果有文字的话