О решении
С помощью этого решения вы можете:
- Переключение темы во время выполнения
- Получить текущую тему во время выполнения
- Тема прямо в CSS без использования дополнительных классов или чего-то еще
- Иметь простое в использовании и понятное решение, которое требует только однократной настройки
Минусы:
- Использует переменные CSS. Некоторые старые браузеры могут их не поддерживать.
- Полагается на более новые версии Angular. Я не знаю, будет ли это работать в более старых версиях (проверено в Angular 6 и 7)
Это то, что я использую в своем проекте прямо сейчас:
Настраивать
Сначала нужно определить тему.
Вот пример с именем dark-theme.scss
, расположенный в src/themes
:
@import '~@angular/material/theming';
@include mat-core();
// Set variables to whatever colors you want for your app
$dark-theme-primary: mat-palette($mat-pink);
$dark-theme-accent: mat-palette($mat-light-blue);
$dark-theme-warn: mat-palette($mat-red);
$dark-theme: mat-dark-theme(
$dark-theme-primary,
$dark-theme-accent,
$dark-theme-warn
);
@include angular-material-theme($dark-theme);
Тогда вам нужна функция SCSS, которая может создавать переменные SCSS и CSS темы:
Вот моя под названием functions.scss
в src/assets/scss
:
@mixin generate-theme-vars($theme) {
//default palette foreground/background:
$foreground-palette: map-get($theme, foreground);
$background-palette: map-get($theme, background);
/////////////////////////////////////////////////
// SCSS VARS
/////////////////////////////////////////////////
$primary: mat-color(map-get($theme, primary));
$accent: mat-color(map-get($theme, accent));
$warn: mat-color(map-get($theme, warn));
$base: mat-color($foreground-palette, base);
$divider: mat-color($foreground-palette, divider);
$dividers: mat-color($foreground-palette, dividers);
$disabled: mat-color($foreground-palette, disabled);
$disabled-button: mat-color($foreground-palette, disabled-button);
$disabled-text: mat-color($foreground-palette, disabled-text);
$hint-text: mat-color($foreground-palette, hint-text);
$secondary-text: mat-color($foreground-palette, secondary-text);
$icon: mat-color($foreground-palette, icon);
$icons: mat-color($foreground-palette, icons);
$text: mat-color($foreground-palette, text);
$slider-off: mat-color($foreground-palette, slider-off);
$slider-off-active: mat-color($foreground-palette, slider-off-active);
$status-bar: mat-color($background-palette, status-bar);
$app-bar: mat-color($background-palette, app-bar);
$background: mat-color($background-palette, background);
$hover: mat-color($background-palette, hover);
$card: mat-color($background-palette, card);
$dialog: mat-color($background-palette, dialog);
$disabled-button: mat-color($background-palette, disabled-button);
$raised-button: mat-color($background-palette, raised-button);
$focused-button: mat-color($background-palette, focused-button);
$selected-button: mat-color($background-palette, selected-button);
$selected-disabled-button: mat-color($background-palette, selected-disabled-button);
$disabled-button-toggle: mat-color($background-palette, disabled-button-toggle);
/////////////////////////////////////////////////
// CSS VARS
/////////////////////////////////////////////////
--primary-color: #{$primary};
--accent-color: #{$accent};
--warn-color: #{$warn};
--base-color: #{$base};
--divider-color: #{$divider};
--dividers-color: #{$dividers};
--disabled-color: #{$disabled};
--disabled-text-color: #{$disabled-text};
--hint-text-color: #{$hint-text};
--secondary-text-color: #{$secondary-text};
--icon-color: #{$icon};
--icons-color: #{$icons};
--text-color: #{$text};
--slider-off-color: #{$slider-off};
--slider-off-active-color: #{$slider-off-active};
--status-bar-color: #{$status-bar};
--app-bar-color: #{$app-bar};
--background-color: #{$background};
--hover-color: #{$hover};
--card-color: #{$card};
--dialog-color: #{$dialog};
--disabled-button-color: #{$disabled-button};
--raised-button-color: #{$raised-button};
--focused-button-color: #{$focused-button};
--selected-button-color: #{$selected-button};
--selected-disabled-button-color: #{$selected-disabled-button};
--disabled-button-toggle-color: #{$disabled-button-toggle};
}
После этого все готово, и все, что вам нужно сделать, это создать класс для каждой темы в вашем глобальном styles.scss
:
@import "functions";
@import "~@angular/material/theming";
// You have to define one of those for every theme you offer
.dark-theme {
@import "themes/dark-theme";
@include angular-material-theme($dark-theme);
@include generate-theme-vars($dark-theme);
}
.light-theme {
@import "themes/light-theme";
@include angular-material-theme($light-theme);
@include generate-theme-vars($light-theme);
}
Применение
Чтобы применить тему, которую вы хотите использовать, вам нужно поместить класс CSS dark-theme
(или как вы его назвали) к элементу, который содержит все остальные элементы.
Я поместил его в HTML-тег:
<!doctype html>
<html lang="en" class="dark-theme">
<!-- ... -->
</html>
Теперь вы можете переключать тему во время выполнения, изменив этот класс с помощью JavaScript, например, на light-theme
.
В каждом свойстве CSS, которому нужен цвет, теперь вы можете использовать переменные:
div {
width: 300px;
height: 300px;
background-color: var(--app-bar-color);
.someText {
color: var(--text-color);
}
}
Если вы хотите что-то сделать в своем CSS, если применена специальная тема и изменение заключается не в самом цвете, то сделайте это так:
// Example: We want to remove some div only when the light-theme is used
div {
width: 300px;
height: 300px;
background-color: var(--app-bar-color);
:host-context(.light-theme) & {
display: none;
}
}
PS
Для всех, кому может быть интересно, почему я использую @import "functions";
, хотя они и находятся в разных папках:
Перейдите в angular.json
и добавьте к объекту projects > <YourProject> > architect > build > options
следующее:
"stylePreprocessorOptions": {
"includePaths": [
"src/assets/scss"
]
},
Теперь вы можете использовать @import "functions";
из любого пути.
Если вам нужна поддержка IE (не проверено, может потребоваться работа)
Поэтому, если вы не можете использовать переменные CSS на некоторых клиентах, вы можете определить запасной вариант для указанных цветов следующим образом:
div {
background-color: red; // fallback to red if the variable doesnt exist -> Old browsers, or IE
background-color: var(--app-bar-color);
}
Зная это, вы могли бы, например, определить несколько переменных SCSS в styles.scss
:
@import "functions";
@import "~@angular/material/theming";
// Default theme
@import "themes/dark-theme";
@include angular-material-theme($dark-theme);
// Generate SCSS vars
$foreground-palette: map-get($theme, foreground);
$background-palette: map-get($theme, background);
/////////////////////////////////////////////////
// SCSS VARS
/////////////////////////////////////////////////
$primary: mat-color(map-get($theme, primary));
$accent: mat-color(map-get($theme, accent));
$warn: mat-color(map-get($theme, warn));
// ... and all the other vars from above if you would like
// You have to define one of those for every theme you offer
.dark-theme {
// Only init the CSS vars here, because the rest is in default
@include generate-theme-vars($dark-theme);
}
.light-theme {
@import "themes/light-theme";
@include angular-material-theme($light-theme);
@include generate-theme-vars($light-theme);
}
Теперь вы можете использовать его так:
div {
background-color: $primary; // fallback
background-color: var(--primary-color);
}
Это больше не может быть изменено динамически с помощью JS во время выполнения!!
person
MauriceNino
schedule
31.07.2019