是否可以在 Twitter-bootstrap 4 $theme-colors 数组中使用 CSS 变量?
Posted
技术标签:
【中文标题】是否可以在 Twitter-bootstrap 4 $theme-colors 数组中使用 CSS 变量?【英文标题】:Is it possible to use CSS variables in Twitter-bootstrap 4 $theme-colors array? 【发布时间】:2019-07-05 02:05:15 【问题描述】:在 bootstrap 4 中,您可以使用以下数组定义和/或覆盖默认颜色:(as documented here)
$theme-colors: (
"primary": #001122, /*override*/
"color-1": red, /*new color*/
"color-2": black, /*new color*/
"color-3": white /*new color*/
);
我想为不同的用户制作自定义主题颜色。用户可以根据身体的类别选择我定义的不同调色板。
我创建了一个新文件来制作我自己的样式,在 body 标签的 CSS 变量中定义我的主题颜色:
body
&.color-pallette-red
--theme-color-1: red;
--theme-color-2: black;
--theme-color-3: white;
color: var(--theme-color-1); /*red*/
&.color-pallette-yellow
--theme-color-1: yellow;
--theme-color-2: black;
--theme-color-3: white;
color: var(--theme-color-1); /*yellow*/
但是这样一来,引导颜色当然不会被覆盖……
我尝试将我的 CSS 变量粘贴到前面提到的引导程序数组中,以确保引导程序使用我的颜色:
$theme-colors: (
"color-1": var(--theme-color-1),
"color-2": var(--theme-color-2),
"color-3": var(--theme-color-3)
);
但这会在运行编译脚本后返回Error: $color2: var(--theme-color-1) is not a color. @return mix($color-base, $color, $level * $theme-color-interval);
。所以引导程序/编译器没有将我的 CSS 变量识别为颜色...
总结我想要的是:根据身体类别更改引导颜色。有谁知道实现这一目标的方法吗?
【问题讨论】:
提供minimal reproducible example,以便我们了解它是如何工作的。 你试过"color-1":#var(--theme-color-1)
引导变量是基于 sass 的,这意味着它们将在构建时生成。因此,您不能将 css 变量注入其中。您所能做的就是在根类中使用不同的变量多次包含整个引导程序。
@TemaniAfif 我试过了,但这给出了同样的错误。
@Sasan Farrokh 我考虑过这个解决方案,但它的可维护性要差得多......
【参考方案1】:
为什么不能在 SASS 中使用 CSS 变量来表示颜色
你不能使用 CSS 变量来表示颜色的原因是像 SASS 中的 darken()
和 lighten()
这样的函数。你可以想象一下,当计算机得到指令时,它会不知道该怎么做:darken( var(--color), 20%)
;您不能修改您不知道的值。
如果我们不使用改变颜色的函数会怎样?
事实上,这应该确实有效。引导库具有使用这些函数的 scss 文件。您可以浏览所有引导代码并删除修改颜色的函数。当然,这将是一些工作。将来更新引导程序会导致您网站的样式神秘地崩溃,并且有人会生您的气。所以这个选项不是一个好主意。
但是...但是...如果 CSS 可以做到,那么您可以使用 SASS 吗?
是的!这就是答案。这将是相当多的工作。如果您使用另一个变量设置颜色,您可以使用像 --color
这样的 SASS 变量来设置这些颜色。例如:
$color1: var(--color-1);
/* It may seem completely redundant to
to define CSS variable here. But
it isn't. You can change the variables in
your browser now with javascript, which
may affect multiple elements.
*/
:root
--color-1: purple;
/* An example on how to change the page
styling with an id.
*/
:root#dark-mode
--color-1: black;
.alert-success
background-color: $color1;
.alert-danger
background-color: $color1;
幸运的是,bootstrap 4 开发人员在保持选择器简单方面做得很好,因此覆盖起来不会太难。请记住在引导 css 之后加载您的 CSS。您可能需要在引导 scss 文件中搜索您要覆盖的 SASS 变量,以确保涵盖所有情况。
祝你好运!
【讨论】:
感谢您的精彩解释。该错误确实可能与颜色函数有关。因为我知道网站上使用了哪些元素,所以我现在将使用这个解决方案,尽管我不喜欢手动覆盖所有内容的想法......【参考方案2】:我喜欢我的其他答案,但我也想提供另一种解决方案,前提是该解决方案不符合项目范围的需求。另一种选择,我认为更直接地满足您的需求,是您可以级联样式表。假设项目树类似于以下内容:
`css\
`--main.css
`--themes.css <- compiled themes.sass
`--themes.sass
`index.html
index.html
:
...
<head>
<link rel="stylesheet" type="text/css" media="screen" href="css/main.css">
<link rel="stylesheet" type="text/css" media="screen" href="css/themes.css">
</head>
<body>
<main class="theme-purple">
<h1>Hello World</h1>
<h2>SASS is fun!</h2>
</main>
<main class="theme-red">
<h1>Hello World</h1>
<h2>SASS is fun!</h2>
</main>
</body>
...
main.css
:
.theme-red
--theme-color-1: red;
--theme-color-2: black;
--theme-color-3: white;
.theme-purple
--theme-color-1: purple;
--theme-color-2: cornflowerblue;
--theme-color-3: white;
在哪里themes.sass
:
@import "node_modules/bootstrap/scss/bootstrap";
$theme-colors: (
"primary": #001122,
"color-1": var(--theme-color-1),
"color-2": var(--theme-color-2),
"color-3": var(--theme-color-3)
);
main
background-color: theme-color("color-1");
h1
color: theme-color("color-2");
h2
color: theme-color("color-3")
这样您的 CSS 变量就有机会被编译。我在 node.js 服务器上进行了测试,因此您应该根据需要更改导入语句
【讨论】:
这实际上是我的想法。但正如@RMo 所说,这在使用诸如 darken () 之类的函数时会出错。 有一个提议将表达式从 SCSS 样式中移出,并允许通过单独的变量 github.com/twbs/bootstrap/issues/31538 来设置它,例如你可以看到一个 PR 显示如何启用 CSS 变量模式 github.com/twbs/bootstrap/pull/31753【参考方案3】:你不能在地图中直接设置 CSS 变量,因为该变量当时不会被编译,因为 SASS 是一个预处理器,另外 bootstrap 会转过来并将这些主题 KVP 转换为 @987654322 @ 变量无论如何,所以你基本上做了两次同样的事情。解决此问题的一种方法是,您可以通过通用 SASS
方法访问地图本身:
...
property: map-get(map-merge($theme-colors,($key : $color)),$key)
...
一旦您设置了特定的 KVP,它就可以在全球范围内用于其他地方。
此时,使用 CSS var()
是任意的,但只是为了涵盖我的所有基础,您可以设置主题,然后更改变量,而不是重新设置和调用 theme-color("color-2")
。
一个完整的例子如下:
@import "bootstrap";
$theme-colors: (
"primary": #001122,
"color-1": black,
"color-2": black,
"color-3": black
);
@function set-theme-color($key, $color)
@return map-get(map-merge($theme-colors,($key : $color)),$key);
@mixin theme($color1, $color2, $color3)
background-color: set-theme-color("color-1", $color1);
h1
color: set-theme-color("color-2", $color2);
h2
color: set-theme-color("color-3", $color3);
main
&.theme-purple
@include theme(purple,cornflowerblue,white);
/* example demonstrating color3 can change */
--color-3: orange;
&.theme-red
@include theme(red,black,white);
h2
color: theme-color("color-2");
h3
/* example demonstrating color3 changed */
color: var(--color-3);
<script src="http://codeply.com/js/embed.js"></script><div data-codeply="o9n2ST6HW5" ></div>
请注意,该示例还演示了一个主题是否设置了变量而其他主题不设置。您选择的主题颜色无效,属性恢复为继承。
codeply demo
【讨论】:
嗨@soulshined,谢谢你的回答。但是如何根据您的示例中的主体类更改引导颜色? 假设我调用“set-theme-color” 20 次,引导变量被重新定义 20 次。假设我在此操作后调用引导颜色,我怎么知道那是哪种颜色? @djl 好吧,假设您在此之后调用引导颜色,您就会知道这是基于范围应用的最后一个规则集,这就是简短的回答。变量是范围驱动的。orange
颜色展示了您将如何知道。在我的示例中,您知道它是橙色的,因为您之前已经设置了它,或者使用 h3
元素设置了它。但是,即使您为红色主题设置了不同的颜色,它也将独立于紫色主题想要什么,因为这正是级联样式表的工作方式。以上是关于是否可以在 Twitter-bootstrap 4 $theme-colors 数组中使用 CSS 变量?的主要内容,如果未能解决你的问题,请参考以下文章
我可以在 twitter-bootstrap popover 数据内容中使用 html 标签吗?
Django Twitter-bootstrap:崩溃不起作用
导航栏顶部的 Twitter-Bootstrap-2 徽标图像