使用动态变量的SCSS主题化

6kkfgxo0  于 2024-01-09  发布在  其他
关注(0)|答案(2)|浏览(174)

Hi All!

我目前正在为CSS框架开发一个主题功能,遇到了一些问题,我希望你能帮忙解决。
我已经创建了一个名为$themes的SASSMap,它包含了不同主题的颜色。我从一篇中等文章中复制粘贴了一些代码(谁没有),并繁荣了我的主题作品!但是...
这一点:

@include themify($themes) {
    .btn {
        color: themed('blue');
    }
}

字符串
在我将要做的大量样式化中,我认为所有的代码都比我认为的要粗糙。
所以...

目标

我想做一些超级hacky和真棒这样的:

@include themify($themes) {
    $blue: themed(blue);
}


我想对变量进行主题化,所以我所要做的就是添加$blue,而不是调用很多mixins和不必要的mumbo jumbo。
如果我能让这样的东西工作,它会看起来像这样:

.btn {
    background: $blue;
}


所有的主题都将提前得到照顾!
当然,这从来都不是那么容易的,因为它不起作用.如果你们中的一个了不起的sass魔术师能用它来施展魔法,那将是一个天赐良机,我将把你们包括在了不起的贡献者的源代码中。
代码
$themes sass-map:

$themes: (
    light: (
        'blue': #0079FF
    ),
    dark: (
        'blue': #0A84FF
    )
);


来自这个令人敬畏的Medium Article的copypasta mixin:

@mixin themify($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);
}


任何关于如何实现这一点的建议都将受到100%的赞赏。非常感谢将您添加到源代码中作为一个令人敬畏的贡献者。
提前感谢!

5vf7fwbs

5vf7fwbs1#

Sass不允许你动态地创建变量--这就是为什么你需要在全局作用域中手动声明变量。

$themes: (
    light: (
        'text': dodgerblue,
        'back': whitesmoke 
    ),
    dark: (
        'text': white,
        'back': darkviolet
    )
);

@mixin themify($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 themed {
    @include themify($themes){
        $text: themed('text') !global;
        $back: themed('back') !global;      
        @content;
    }
}

@include themed {
    div {
        background: $back;
        color: $text; 
        border: 1px solid; 
    }
}

字符串
这种方法的问题(除了维护起来很繁琐之外)是它会用与主题无关的东西来膨胀你的CSS-在上面的例子中,边界将被重复。

.theme-light div {
  background: whitesmoke;
  color: dodgerblue;
  border: 1px solid; //  <= 
}

.theme-dark div {
  background: darkviolet;
  color: white;
  border: 1px solid; // <=
}


虽然我认为有可能创建一个设置,每个主题的范围,它自己的个人风格(如light.css和dark.css),我认为你应该考虑使用CSS变量来处理这一点

$themes: (
    light: (
        'text': dodgerblue,
        'back': whitesmoke 
    ),
    dark: (
        'text': white,
        'back': darkviolet
    )
);

@each $name, $map in $themes {
    .theme-#{$name} {
        @each $key, $value in $map {
            --#{$key}: #{$value};
        }
    }
} 

div {
    background: var(--back);
    color: var(--text); 
    border: 1px solid;
}


CSS输出

.theme-light {
  --text: dodgerblue;
  --back: whitesmoke;
}

.theme-dark {
  --text: white;
  --back: darkviolet;
}

div {
  background: var(--back);
  color: var(--text);
  border: 1px solid;
}


注意!你只需要添加主题类到例如body标签,嵌套的元素将继承值:)

ee7vknir

ee7vknir2#

我会使用这样的方法(它看起来有点简单):

$themes-names: (
    primary: (
        background: $white,
        color: $dark-grey,
        font-size: 18px,
    ),
    dark: (
        background: $dark,
        font-size: 10px,
    )
);
$primaryName: "primary";
$darkName: "dark";

@function map-deep-get($map, $keys...) {
    @each $key in $keys {
        $map: map-get($map, $key);
    }
    @return $map;
}

@mixin print($declarations) {
    @each $property, $value in $declarations {
        #{$property}: $value
    }
}

@mixin wrappedTheme($declarations) {
    @each $theme, $value in $declarations {
        $selector: "&.theme-#{$theme}";
        #{$selector} {
            @include print(map-deep-get($themes-names, $theme));
        }
    }
}


$color-default: map-deep-get($themes-names, "primary", "color");

.button-themed {
    /*extend some shared styles*/
    @extend %button;

    /* generate &.theme-primary{...} and &.theme-dark{...} */
    @include wrappedTheme($themes-names); 

    /*override*/
    &.theme-#{$darkName} {
        border: 5px solid $color-default;
        color: $white;
    }

    /* can override/extend specific theme  --modifier */
    &.theme-#{$primaryName}--modifier {
        @include print(map-deep-get($themes-names, $primaryName)); 
        /* will add all from: $themes-names[$primaryName]
        /---
            background: $white,
            color: $dark-grey,
            font-size: 18px,
        */
        font-size: 22px;
    }

    color: $color-default;
}

字符串

相关问题