Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Css 如何在SCS中实现可切换主题?_Css_Sass - Fatal编程技术网

Css 如何在SCS中实现可切换主题?

Css 如何在SCS中实现可切换主题?,css,sass,Css,Sass,我有一个使用语义变量的scss文件的现有项目: $background-color: white; body { background-color: $background-color; } 我想在向主体添加主题类时将背景更改为黑色: <body class="theme-dark">...</body> 更新(基于Amar的回答): .theme-light { --background-color: white; } :ro

我有一个使用语义变量的scss文件的现有项目:

$background-color: white;

body {
    background-color: $background-color;
}
我想在向主体添加主题类时将背景更改为黑色:

<body class="theme-dark">...</body>
更新(基于Amar的回答):

.theme-light {
    --background-color: white;
}
:root {
    --background-color: white;
}
.theme-dark {
    --background-color: black;
}

$background-color: var(--background-color);
body {
    background-color: $background-color;
}
将scss变量定义为具有css变量扩展作为值,即(从上面开始):

生成以下css:

:root { --background-color: white; }
.theme-dark { --background-color: black; }
body { background-color: var(--background-color); }
这似乎是我们想要的


我喜欢它,因为它只需要更改
$background color
的定义(不是在非常大的scss文件中的所有用法),但我不确定这是否是一个合理的解决方案?我对scss还很陌生,所以可能我错过了一些功能。

使用scss可以做到这一点,但您必须将样式添加到所有要设置主题的元素中。这是因为SCS是在构建时编译的,不能用类切换变量。例如:

$background-color-white: white;
$background-color-black: white;

body {
  background-color: $background-color-white;
}

.something-else {
  background-color: $background-color-white;
}

// Dark theme
body.theme-dark {
  background-color: $background-color-black;

  .something-else {
    background-color: $background-color-black;
  }
}
目前最好的方法是使用CSS变量。您可以这样定义默认变量:

:root {
  --background-color: white;
  --text-color: black;
}

.theme-dark {
  --background-color: black;
  --text-color: white;
}
body {
  background-color: var(--background-color);
  color: var(--text-color);
}
然后,在元素中使用这些变量,如下所示:

:root {
  --background-color: white;
  --text-color: black;
}

.theme-dark {
  --background-color: black;
  --text-color: white;
}
body {
  background-color: var(--background-color);
  color: var(--text-color);
}
如果
body
元素具有
主题类,它将使用为该类定义的变量。否则,它将使用默认的根变量。

所有信用都归Dmitry Borody所有 我会推荐一种类似于中提到的方法。使用这种方法,您可以指定需要设置主题的类,而无需特别提及主题名称,这样就可以同时应用多个主题

首先,设置包含主题的SASS映射。关键点可以是对您有意义的任何东西,只要确保每个主题对同一事物使用相同的名称即可

$themes: (
  light: (
    backgroundColor: #fff,
    textColor: #408bbd,
    buttonTextColor: #408bbd,
    buttonTextTransform: none,
    buttonTextHoverColor: #61b0e7,
    buttonColor: #fff,
    buttonBorder: 2px solid #fff,
  ),
  dark: (
    backgroundColor: #222,
    textColor: #ddd,
    buttonTextColor: #aaa,
    buttonTextTransform: uppercase,
    buttonTextHoverColor: #ddd,
    buttonColor: #333,
    buttonBorder: 1px solid #aaa,
  ),
);
然后使用
mixin
函数
对添加主题支持

body {
  background-color: white;
  @include themify {
    background-color: theme( 'backgroundColor' );
  }
}

.button {
  background-color: lightgray;
  color: black;

  @include themify {
    background-color: theme( 'buttonBackgrounColor' );
    color: theme( 'buttonTextColor' );
  }

  &:focus,
  &:hover {
    background-color: gray;
    
    @include themify {
      background-color: theme( 'buttonBackgroundHoverColor' );
      color: theme( 'buttonTextHoverColor' );
    }
  }
}
如果你要添加很多主题,或者一个主题会涉及很多东西,你可能希望设置你的SCSS文件有点不同,这样所有的主题都不会在你的主CSS文件中膨胀(就像上面的例子那样)。一种方法是创建一个
themes.scss
文件,复制任何需要设置主题的选择器路径,并使用第二个生成脚本只输出
themes.scss
文件

混音器

@mixin themify( $themes: $themes ) {
  @each $theme, $map in $themes {

    .theme-#{$theme} & {
      $theme-map: () !global;
      @each $key, $submap in $map {
        $value: map-get(map-get($themes, $theme), '#{$key}');
        $theme-map: map-merge($theme-map, ($key: $value)) !global;
      }

      @content;
      $theme-map: null !global;
    }

  }
}
@function themed( $key ) {
  @return map-get( $theme-map, $key );
}
功能

@mixin themify( $themes: $themes ) {
  @each $theme, $map in $themes {

    .theme-#{$theme} & {
      $theme-map: () !global;
      @each $key, $submap in $map {
        $value: map-get(map-get($themes, $theme), '#{$key}');
        $theme-map: map-merge($theme-map, ($key: $value)) !global;
      }

      @content;
      $theme-map: null !global;
    }

  }
}
@function themed( $key ) {
  @return map-get( $theme-map, $key );
}

您是否建议不要定义和使用
$background color
scss变量?@比约恩我刚刚更新了我的答案,以展示如何使用scss实现这一点。对于主题化,我建议您使用SCSS变量,因为您可以随时切换这些变量,而不必为主题自定义的所有元素设置样式。@Bjorn取决于,CSS变量可能不适合您。@hungerstar谢天谢地,这不是问题(是的,我知道我很幸运;-)@AmarSyla我刚刚更新了这个问题,详细介绍了如何将css变量作为scss变量的值编译到您答案中的最后一个代码块中。我在第一条评论中的问题是,您是否建议不要以这种方式混合css变量和scss变量?这当然令人印象深刻:-)我不确定我会称之为轻量级,而且它需要更改现有(非常大)scss文件中的几乎每一条规则…为什么您必须更改规则(假设你指的是CSS选择器)?你只需添加
@include themify{}
其中需要添加主题样式,并将
主题
函数与属性值一起使用。由@AmarSyla提供的SCSS解决方案将需要相同的工作量,CSS变量解决方案将是最精简的,但我可以看出人们可能不希望所有
--background color
的实例都切换。在这种情况下,y你将处理更多的变量,并拥有与SCSS解决方案类似的开销。如果一个小函数和一个小混入不是轻量级的,那么我不知道该告诉你什么。这将起作用,直到你决定说
darken($background color,10%);
@YuryTarabanko啊..我知道一定有这样的事情:-/