Можно ли использовать CSS-переменные в массиве Twitter-bootstrap 4 $ theme-colors?

В начальной загрузке 4 вы можете определить и/или переопределить цвета по умолчанию, используя следующий массив: (как описано здесь)

$theme-colors: (
    "primary": #001122, /*override*/
    "color-1": red, /*new color*/
    "color-2": black, /*new color*/
    "color-3": white /*new color*/
);

Я хочу сделать собственные цвета темы для разных пользователей. Пользователи могут выбирать разные цветовые палитры, которые я определил в зависимости от класса тела.

Я создал новый файл для создания своих собственных стилей, определяя цвета моей темы в переменных CSS в теге body:

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); Error: $color2: var(--theme-color-1) is not a color. @return mix($color-base, $color, $level * $theme-color-interval); после запуска скрипта компиляции. Таким образом, загрузчик/компилятор не распознал мои CSS-переменные как цвет...

Подводя итог, я хочу: изменить цвета начальной загрузки в зависимости от класса тела. Кто-нибудь знает способ добиться этого?

Ответ 1

Вы не можете установить CSS-переменные в картах напрямую, потому что эта переменная не будет скомпилирована в данный момент, так как SASS является препроцессором, кроме того, bootstrap оборачивается и конвертирует эти тематические KVP в :root переменные в любом случае, так что вы по сути делаете одно и то же дважды. Одним из способов решения этой проблемы является то, что вы можете просто подключиться к самой карте с помощью общих методов 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>

Ответ 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, поэтому вы должны изменить оператор импорта по мере необходимости

Ответ 3

Почему вы не можете использовать переменные CSS для цветов в SASS

Причиной, по которой вы не можете использовать CSS-переменные для цветов, являются такие функции, как darken() и lighten() в SASS. Вы можете представить, что компьютер не будет знать, что делать, когда получит инструкцию: darken( var(--color), 20%); Вы не можете изменить значение, о котором вы не знаете.

Что если мы просто не используем функции, которые меняют цвета?

На самом деле это должно работать. В библиотеке начальной загрузки есть scss файлы, которые используют эти функции. Вы можете пройти через весь загрузочный код и удалить функции, которые изменяют цвета. Конечно, это будет немного работы. Обновление начальной загрузки в будущем может привести к таинственному краху стиля вашего сайта, и кто-то будет очень зол на вас. Так что этот вариант не очень хорошая идея.

Но... Но... Если CSS может сделать это, вы можете с SASS?

ДА! Это ответ. И это будет довольно много работы. Если вы устанавливаете цвета с помощью другой переменной, вы можете использовать переменную SASS, например, --color для этих цветов. Например:

  $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, которую вы переопределяете, чтобы убедиться, что вы охватили все случаи.

Удачи!