是否可以在 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);

&lt;script src="http://codeply.com/js/embed.js"&gt;&lt;/script&gt;&lt;div data-codeply="o9n2ST6HW5" &gt;&lt;/div&gt;

请注意,该示例还演示了一个主题是否设置了变量而其他主题不设置。您选择的主题颜色无效,属性恢复为继承。

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 徽标图像

带有 twitter-bootstrap 的下拉菜单

Twitter-bootstrap 模式未在页面加载时显示(灰屏)

如何让 twitter-bootstrap 导航栏子项在小屏幕上折叠/展开?