Мне поставили задачу добавить переключатель в веб-приложение angular, которое позволит пользователям переключаться с темы светлого режима по умолчанию на тему темного режима. Я не могу найти способ успешно реализовать это.
Когда я получил задание, в каталоге стилей был файл _variables.scss. Он содержал переменные для цветов, шрифтов, размеров и интервалов. Цвета были в картах, а затем каждый оттенок был назначен переменной с использованием метода map-get(), например, $shade-0: map-get($shades, 'shade-0').
Сначала я думал, что могу создать файл themes.scss и импортировать его вместе с _variables.scss. Затем этот файл будет связан с двумя дополнительными файлами scss lightTheme.scss и darkTheme.scss. Каждый файл темы будет содержать список переменных цвета, похожих на исходные в variables.scss. Я могу заставить это работать для одной темы или другой, но я не могу переключаться между файлами темы.
darkTheme.scss
$shades: (
'shade-6': #f5f5f5,
'shade-5': #BDBDBD,
'shade-4': #9E9E9E,
'shade-3': #757575,
'shade-2': #616161,
'shade-1': #303437,
'shade-0': #404447,
);
$shade-0: map-get($shades, 'shade-0');
$shade-1: map-get($shades, 'shade-1');
$shade-2: map-get($shades, 'shade-2');
$shade-3: map-get($shades, 'shade-3');
$shade-4: map-get($shades, 'shade-4');
$shade-5: map-get($shades, 'shade-5');
$shade-6: map-get($shades, 'shade-6');
$colors: (
'forest': #239F28CC,
'aqua': #8ab4f8,
'ruby': #C93939CC,
'zing': #20CAC3CC,
'carrot': #E9853ECC,
'grape': #7542F2CC,
'midnight': #433F5CCC,
'slate': #657786CC,
);
$forest: map-get($colors, 'forest');
$aqua: map-get($colors, 'aqua');
$ruby: map-get($colors, 'ruby');
$zing: map-get($colors, 'zing');
$carrot: map-get($colors, 'carrot');
$grape: map-get($colors, 'grape');
$midnight: map-get($colors, 'midnight');
$slate: map-get($colors, 'slate');
$bg-color: map-get($shades, 'shade-1');
$border-color: map-get($shades, 'shade-2');
$border-dark-color: map-get($shades, 'shade-3');
$text-color: map-get($shades, 'shade-6');
$muted: map-get($colors, 'slate');
$subtle: map-get($shades, 'shade-4');
lightTheme.scss
$colors: (
'forest': #239F28,
'aqua': #186EEF,
'ruby': #C93939,
'zing': #20CAC3,
'carrot': #E9853E,
'grape': #7542F2,
'midnight': #433F5C,
'slate': #657786,
);
$shades: (
'shade-0': #ffffff,
'shade-1': #f5f5f5,
'shade-2': #d8d8d8,
'shade-3': #bbbbbb,
'shade-4': #979797,
'shade-5': #535353,
'shade-6': #0c0c0c,
);
$shade-0: map-get($shades, 'shade-0');
$shade-1: map-get($shades, 'shade-1');
$shade-2: map-get($shades, 'shade-2');
$shade-3: map-get($shades, 'shade-3');
$shade-4: map-get($shades, 'shade-4');
$shade-5: map-get($shades, 'shade-5');
$shade-6: map-get($shades, 'shade-6');
$forest: map-get($colors, 'forest');
$aqua: map-get($colors, 'aqua');
$ruby: map-get($colors, 'ruby');
$zing: map-get($colors, 'zing');
$carrot: map-get($colors, 'carrot');
$grape: map-get($colors, 'grape');
$midnight: map-get($colors, 'midnight');
$slate: map-get($colors, 'slate');
$bg-color: map-get($shades, 'shade-1');
$border-color: map-get($shades, 'shade-2');
$border-dark-color: map-get($shades, 'shade-3');
$text-color: map-get($shades, 'shade-6');
$muted: map-get($colors, 'slate');
$subtle: map-get($shades, 'shade-4');
темы.scss
@import 'global/lightTheme';
@import 'global/darkTheme';
Я попытался изменить переменные с переменных scss на переменные css и использовать их с var(), но столкнулся с трудностями, поскольку некоторые компоненты используют darken(), lighten() и mix() и поэтому не компилируются. Есть ли способ заставить это работать?






Я подготовил CodePen для демонстрации переключения темы с помощью переменных CSS.
Я определяю переменные цвета в зависимости от класса контейнера приложения (.light или .dark). Простое переключение этих классов изменит тему сайта.
Имейте в виду, что Переменные CSS не полностью поддерживаются во всех браузерах. (94% по всему миру).
Это действительно здорово @Barthy, это достаточно близко к тому, что мне нужно. Это решит большинство моих проблем, за исключением того, что в моем приложении есть определенные компоненты, в которых один из цветов становится темнее, например background-color: darken($bg-color, 8%); . Точно так же используются lighten() и mix(). Я знаю, что переменные CSS и SCSS плохо сочетаются друг с другом. У вас есть предложения?
Да, определите более темные цвета так же, как и все остальные цвета, и используйте их позже! Я обновлю перо с примером.
@BenNewton, вы видели обновление, которое я сделал в ручка?
Да, я сделал. Большое спасибо за вашу помощь, это сработало!
Я нашел этот статья на Medium, думаю, вы можете его проверить.
Идея заключается в том, что вы запрашиваете тег body в своем html, а затем устанавливаете для него класс
Этот вопрос был задан год назад, но все еще полезен для тех, кто читает это, вот более простое решение.
Все, что вам нужно сделать в вашем файле scss, это:
.content {
padding: 32px;
@include theme() {
color: theme-get('text-color');
background-color: theme-get('bg-color');
}
}
Вы можете создать отдельный файл, скажем, themes.scss, в котором вы можете определить свойства для обеих ваших тем:
$themes: (
darkTheme: (
'text-color': white,
'bg-color': #424242
),
lightTheme: (
'text-color': black,
'bg-color': #f5f5f5
)
);
Используйте mixin:
// From Sass 2.0 on, it is no longer allowed to declare globals on the fly.
$theme-map: null;
@mixin theme() {
@each $theme, $map in $themes {
// $theme: darkTheme, lightTheme
// $map: ('text-color': ..., 'bg-color': ...)
// make the $map globally accessible, so that theme-get() can access it
$theme-map: $map !global;
// make a class for each theme using interpolation -> #{}
// use & for making the theme class ancestor of the class
// from which you use @include theme() {...}
.#{$theme} & {
@content; // the content inside @include theme() {...}
}
}
// no use of the variable $theme-map now
$theme-map: null !global;
}
Теперь вы можете получить доступ к свойству темы, используя map-get($theme-map, ...). Но мы можем избежать передачи $theme-map в качестве аргумента каждый раз, определив функцию, которая сделает это за нас.
@function theme-get($key) {
@return map-get($theme-map, $key);
}
Результирующий файл css будет:
.content {
padding: 32px;
}
.darkTheme .content {
color: white;
background-color: #424242;
}
.lightTheme .content {
color: black;
background-color: #f5f5f5;
}
Вот скрипт для демонстрации: https://jsfiddle.net/aksh101099/zubnapr9/1/
Это прекрасное решение! Работает как шарм, спасибо за это!
Разве это не создает двойной CSS? (так что если у вас 10 тем, то в 10 раз больше css). Хотя сами решения работают нормально, в некоторых случаях придерживаться переменных css, то есть :root { --sth: xxx} и var(--sth) si, можно.
Чтобы согласиться с ответом Акшдипа Сингха, если вы используете модули css (или scss), вам нужно будет определить ключевое слово темы в своем селекторе как глобальное, чтобы к нему не применялось имя модуля:
@mixin theme() {
@each $theme, $map in $themes {
// $theme: darkTheme, lightTheme
// $map: ('text-color': ..., 'bg-color': ...)
// make the $map globally accessible, so that theme-get() can access it
$theme-map: $map !global;
// make a class for each theme using interpolation -> #{}
// use & for making the theme class ancestor of the class
// from which you use @include theme() {...}
:global(.#{$theme}) & {
@content; // the content inside @include theme() {...}
}
}
// no use of the variable $theme-map now
$theme-map: null !global;
}
вы можете импортировать стили с условиями, перейдите по этой ссылке: stackoverflow.com/questions/36367532/…