我目前正在开发 CSS 框架的主题功能,并遇到了一些问题,希望您能够帮助解决。
我创建了一个名为
$themes
的 SASS 地图,其中包含不同主题的颜色。我从一篇中等文章中复制粘贴了一些代码(谁没有),然后我的主题就成功了!
但是...@include themify($themes) {
.btn {
color: themed('blue');
}
}
开。每一个。成分。是比我认为在我将要做的大量样式中可维护的代码更草率的代码。
所以...
我想做一些像这样超级黑客和很棒的事情:
@include themify($themes) {
$blue: themed(blue);
}
我想对变量进行主题化,所以我所要做的就是添加
$blue
,而不是大量调用 mixin 和不必要的胡言乱语。.btn {
background: $blue;
}
所有主题都会事先处理好!
但当然,这从来都不是那么容易,因为它不起作用...如果你们中的一位很棒的
sass
魔术师能够用这个来施展一些魔法,那将是天赐之物,我会将你包含在很棒的贡献者的源代码中。
$themes
sass 地图:
$themes: (
light: (
'blue': #0079FF
),
dark: (
'blue': #0A84FF
)
);
来自这篇很棒的Medium文章的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% 受到赞赏。非常感谢您将您作为出色的贡献者添加到源代码中。
预先感谢!
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 标签和嵌套元素将继承这些值:)
我会使用这样的方法(看起来更简单):
$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;
}