-
Notifications
You must be signed in to change notification settings - Fork 6.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow overriding of theme background and foreground colors #6244
Comments
Should developers be encouraged to set background colors of a theme? Or do we just want documentation on using the background color from a theme? put differently: |
@literalpie : I'd like to know how to set background colors of a theme when I create it. |
@fabienbranchel example: https://stackblitz.com/edit/angular-material-custom-background?file=theme.scss I don't know if this method is recommended or officially supported - therefore, I'm not sure if it should be added to the documentation. It seems to me like it would be a better fit for a blog post. |
Would be nice if those 2 functions were similar to how red has defaults to allow overriding without copy/pasting: // Creates a container object for a light theme to be given to individual component theme mixins.
@function mat-light-theme($primary, $accent, $warn: mat-palette($mat-red), $foreground: mat-palette($mat-light-theme-foreground), $background: mat-palette($mat-light-theme-background)) {
@return (
primary: $primary,
accent: $accent,
warn: $warn,
is-dark: false,
foreground: $foreground,
background: $background,
);
}
// Creates a container object for a dark theme to be given to individual component theme mixins.
@function mat-dark-theme($primary, $accent, $warn: mat-palette($mat-red), $foreground: mat-palette($mat-dark-theme-foreground), $background: mat-palette($mat-dark-theme-background)) {
@return (
primary: $primary,
accent: $accent,
warn: $warn,
is-dark: true,
foreground: $foreground,
background: $background,
);
} Or better yet, just don't use those functions:
To be honest whilst reading into all of the helpers the |
I have also struggled to find a way to set the app background, and unfortunately the proposed solutions do not work if the app is not wrapped in a material component. For example, in @literalpie 's example, the app is wrapped inside a The only way i have found to set the background for
That will work, provided that you have declared the Of course you can provide any color, that is independent of the theme you have created, but this might be harder to maintain. |
Are you saying that instead of having the two functions, someone would use the dark theme by passing the foreground and background? I could get on board with that. |
🤦♂ OK, i have totally missed that! 🤣 FWIW, my solution, applies the background color even before the app.component is bootstraped, which in my case makes a custom loading spinner i have, being displayed using the theme background color. Instead, adding the |
i am trying to use angular material with a theme built in scss,angular,bootstrap , i have install it using npm and add all the neccessary files, also it is not showing any error yet i am not able to use it components |
Just add Material theming in your angular project.
then choose custom theming option and paste the below code you will get black dark theming and if you wanna customize material color scheme then go to https://material.io and go material color palette and select your custom color scheme for your navbar and button(other components).
|
Just found this thread. I've been trying to figure out themes for a long time. Couldn't find a concrete solution until now. Making it work by adding However, if I don't have enough content on the window then the rest of the background remains white(default color) only. So you would need to modify the style of I have applied the theme toggle in my header and as per Angular Material docs, added an extra class to the custom_theme.scss @import "~@angular/material/theming";
@include mat-core();
// LIGHT THEME
$light-primary: mat-palette($mat-indigo);
$light-accent: mat-palette($mat-yellow, A200, A100, A400);
$light-warn: mat-palette($mat-red);
$light-theme: mat-light-theme($light-primary, $light-accent, $light-warn);
@include angular-material-theme($light-theme);
// DARK THEME
$dark-primary: mat-palette($mat-grey);
$dark-accent: mat-palette($mat-amber, A200, A100, A400);
$dark-warn: mat-palette($mat-red);
// Create the theme object (a Sass map containing all of the palettes).
$dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn);
.dark-theme {
@include angular-material-theme($dark-theme);
} app.component.html <div id="alternative-theme">
<mat-sidenav-container class="app-container">
<app-header></app-header>
<router-outlet> </router-outlet>
<app-footer></app-footer>
</mat-sidenav-container>
</div> app.component.css #alternative-theme {
display: block;
height: 100%;
}
.app-container {
height: inherit;
} theme.service.ts import { Injectable } from "@angular/core";
import { OverlayContainer } from "@angular/cdk/overlay";
@Injectable({
providedIn: "root"
})
export class ThemeService {
constructor(private overlayContainer: OverlayContainer) {
this.overlayContainer = overlayContainer;
}
setDarkTheme() {
document.getElementById("alternative-theme").classList.add("dark-theme");
document.getElementById("footer-text").classList.remove("dark");
this.overlayContainer.getContainerElement().classList.add("dark-theme");
}
setLightTheme() {
document.getElementById("alternative-theme").classList.remove("dark-theme");
document.getElementById("footer-text").classList.add("dark");
this.overlayContainer.getContainerElement().classList.remove("dark-theme");
document;
}
} Is this the best way to toggle between themes or is there a more robust way? I'm just starting with Angular and Material UI and if you have anything to add to the above snippets to make it better will be appreciated. Cheers. |
Just put the classes on your body or app: <body class="mat-typography mat-app-background">
<app-root></app-root>
</body> @see https://material.angular.io/guide/theming#using-a-pre-built-theme
|
Adding onto @intellix proposal: It'd be backwards compatible to change the current @function mat-light-theme(...) {
// ...
$result: $primary;
@if map_get($primary, color) {
$color-settings: map_get($primary, color);
$primary: map_get($color-settings, primary);
$accent: map_get($color-settings, accent);
$warn: map_get($color-settings, warn);
$foreground: map_get($color-settings, foreground);
$background: map_get($color-settings, background);
$result: map_merge($result, (color: _mat-create-light-color-config($primary, $accent, $warn, $foreground, $background)));
}
@return _mat-create-backwards-compatibility-theme(_mat-validate-theme($result));
}
@function _mat-create-light-color-config($primary, $accent, $warn: null, $foreground: $mat-light-theme-foreground, $background: $mat-light-theme-background) {
@return (
primary: $primary,
accent: $accent,
warn: if($warn != null, $warn, mat-palette($mat-red)),
is-dark: false,
foreground: $foreground,
background: $background,
);
} This way, guarantees that people using the older stuff still works (since it defaults to the global variables) and yet people who want can use the cleaner method: $theme: mat-light-theme((
color: (
primary: $primary,
accent: $accent,
warn: $warn,
background: (
app-bar: #fff,
),
),
)); Right now the equivalent of the above usage is: $mat-light-theme-background: map_merge($mat-light-theme-background, (
app-bar: #fff,
));
$theme: mat-light-theme((
color: (
primary: $primary,
accent: $accent,
warn: $warn,
),
)); |
Hopefully this gets added soon. It is pretty annoying to being able to set primary, accent and warn palettes, and not being able to set the foreground and background ones in an easy and clean way too. (Right now using the accepted answer at https://stackoverflow.com/questions/43919927/angular-material2-theming-how-to-set-app-background) |
Can this please added soon. Thx. |
It took me days to find this issue from 2017... phew. |
OK, I managed to also apply the light/dark toggling to the whole app by putting everything in a container of class 'mat-app-background'. |
I actually disagree with this assertion. I've been working through this myself recently, and you pretty much have to dig deeply into the theming api to figure out how to override the base background color. If we could pass some subset of the foreground and background theme object (just the things we care about overriding) into the define theme functions, and those partials are merged with what's being set by default, then that would seem like the best of both worlds. I basically had to do a map.deep-merge, after the theme was defined to augment the background palette that was generated by default. I didn't care about overriding everything, just a handful of surface properties. |
I just want to change the 'text' colour from the 'foreground' map. You used to be able to do it like described here: https://newbedev.com/how-to-change-font-color-of-primary-palette-in-angular-material2 Why can't we support something like:
so I can change the text colour to whatever I want. |
Yep, passing in the foreground and background overrides, and the define-*-theme function merging those onto the default would be my preference too. The only way I've been able to do it, is use the define function to generate the theme object, and then override those props after the fact. It's hacky, and i'd much prefer a way to do it that's officially supported, but it works for now. |
This function (and the dark theme version) is what would likely need to change, to allow for those parameters, instead of only taking defaults. components/src/material/core/theming/_theming.scss Lines 114 to 123 in c649f7d
Ideally it would start with the defaults and merge in whatever overrides are passed in. So that the entire map doesn't need to be defined. |
Until a fix is added. just bypass the create theme function in your main style file. see solution: https://stackblitz.com/edit/angular-material-custom-background?file=theme.scss |
Don't work:
It would be nice to have easy way to change background and foreground |
I agree that providing a way to easily customizing foreground and background colors would be a blast. src/app/core/theming/_palette.scss @use "sass:map";
// Of course you can customize everything ;)
$dark-primary-text: rgba(#000939, 0.87);
$dark-secondary-text: rgba(#000939, 0.54);
$dark-disabled-text: rgba(#000939, 0.38);
$dark-dividers: rgba(#000939, 0.12);
$dark-focused: rgba(#000939, 0.12);
$light-primary-text: white;
$light-secondary-text: rgba(white, 0.7);
$light-disabled-text: rgba(white, 0.5);
$light-dividers: rgba(white, 0.12);
$light-focused: rgba(white, 0.12);
$grey-palette: (
50: #f7f9ff,
100: #f1f3fb,
200: #e8eaf2,
300: #d9dbe3,
400: #b5b7bf,
500: #96979f,
600: #6d6f76,
700: #5a5b62,
800: #3b3d43,
900: #1b1c22,
contrast: (
50: $dark-primary-text,
100: $dark-primary-text,
200: $dark-primary-text,
300: $dark-primary-text,
400: $dark-primary-text,
500: $dark-primary-text,
600: $light-primary-text,
700: $light-primary-text,
800: $light-primary-text,
900: $light-primary-text,
),
);
$night-palette: (
50: #e3ecff,
100: #bed1e9,
200: #9eb1ce,
300: #7c92b2,
400: #637c9e,
500: #4a668b,
600: #3c597a,
700: #2d4664,
800: #1e344e,
900: #0b2137,
contrast: (
50: $dark-primary-text,
100: $dark-primary-text,
200: $dark-primary-text,
300: $light-primary-text,
400: $light-primary-text,
500: $light-primary-text,
600: $light-primary-text,
700: $light-primary-text,
800: $light-primary-text,
900: $light-primary-text,
),
);
// Background palette for light themes.
$light-theme-background-palette: (
status-bar: map.get($grey-palette, 300),
app-bar: white,
background: map.get($grey-palette, 50),
hover: rgba(#243b53, 0.04),
card: white,
dialog: white,
disabled-button: rgba(#243b53, 0.12),
raised-button: white,
focused-button: $dark-focused,
selected-button: map.get($grey-palette, 300),
selected-disabled-button: map.get($grey-palette, 400),
disabled-button-toggle: map.get($grey-palette, 200),
unselected-chip: map.get($grey-palette, 200),
disabled-list-option: map.get($grey-palette, 200),
tooltip: map.get($grey-palette, 700),
);
// Background palette for dark themes.
$dark-theme-background-palette: (
status-bar: #0b2844,
app-bar: map.get($night-palette, 900),
background: #102a43,
hover: rgba(white, 0.04),
card: map.get($night-palette, 800),
dialog: map.get($night-palette, 800),
disabled-button: rgba(white, 0.12),
raised-button: map.get($night-palette, 800),
focused-button: $light-focused,
selected-button: map.get($night-palette, 900),
selected-disabled-button: map.get($night-palette, 800),
disabled-button-toggle: #243b53,
unselected-chip: map.get($night-palette, 700),
disabled-list-option: #243b53,
tooltip: map.get($night-palette, 700),
);
// Foreground palette for light themes.
$light-theme-foreground-palette: (
base: #243b53,
divider: $dark-dividers,
dividers: $dark-dividers,
disabled: $dark-disabled-text,
disabled-button: rgba(#243b53, 0.26),
disabled-text: $dark-disabled-text,
elevation: #243b53,
hint-text: $dark-disabled-text,
secondary-text: $dark-secondary-text,
icon: rgba(#243b53, 0.54),
icons: rgba(#243b53, 0.54),
text: rgba(#243b53, 0.87),
slider-min: rgba(#243b53, 0.87),
slider-off: rgba(#243b53, 0.26),
slider-off-active: rgba(#243b53, 0.38),
);
// Foreground palette for dark themes.
$dark-theme-foreground-palette: (
base: white,
divider: $light-dividers,
dividers: $light-dividers,
disabled: $light-disabled-text,
disabled-button: rgba(white, 0.3),
disabled-text: $light-disabled-text,
elevation: black,
hint-text: $light-disabled-text,
secondary-text: $light-secondary-text,
icon: white,
icons: white,
text: white,
slider-min: white,
slider-off: rgba(white, 0.3),
slider-off-active: rgba(white, 0.3),
); src/app/core/theming/_theming.scss @use '@angular/material' as mat;
@use 'sass:map';
@use 'palette';
@function define-light-theme($config) {
$theme: mat.define-light-theme($config);
$color: map.get($theme, color);
$color: map.merge(
$color,
(
background: palette.$light-theme-background-palette,
foreground: palette.$light-theme-foreground-palette,
)
);
@return map.merge(
$theme,
(
color: $color,
)
);
}
@function define-dark-theme($config) {
$theme: mat.define-dark-theme($config);
$color: map.get($theme, color);
$color: map.merge(
$color,
(
background: palette.$dark-theme-background-palette,
foreground: palette.$dark-theme-foreground-palette,
)
);
@return map.merge(
$theme,
(
color: $color,
)
);
} core/theming/_index.scss @forward "palette";
@forward "theming";
// Here you can forward your own themes located in core/themeing/themes
// @forward "themes/xxxx" as xxxx-*;
// ... src/styles.scss @use "@angular/material" as mat;
@use "app/core/theming" as app;
@use "sass:map";
@include mat.core();
$app-primary: mat.define-palette(mat.$indigo-palette);
$app-accent: mat.define-palette(mat.$pink-palette);
// Use your own "app" define-light-theme function instead of "mat" one.
$app-theme: app.define-light-theme(
(
color: (
primary: $app-primary,
accent: $app-accent,
)
)
); |
@MikaStark trying to work around with your example in material v13, but it doesn't change anything to the theme. palette.scss @use "sass:map";
// Of course you can customize everything ;)
$dark-primary-text: rgba(#000939, 0.87);
$dark-secondary-text: rgba(#000939, 0.54);
$dark-disabled-text: rgba(#000939, 0.38);
$dark-dividers: rgba(#000939, 0.12);
$dark-focused: rgba(#000939, 0.12);
$light-primary-text: white;
$light-secondary-text: rgba(white, 0.7);
$light-disabled-text: rgba(white, 0.5);
$light-dividers: rgba(white, 0.12);
$light-focused: rgba(white, 0.12);
$grey-palette: (
50: #f8fafc,
100: #f1f5f9,
200: #e2e8f0,
300: #cbd5e1,
400: #94a3b8,
500: #64748b,
600: #475569,
700: #334155,
800: #1e293b,
900: #0f172a,
contrast: (
50: $dark-primary-text,
100: $dark-primary-text,
200: $dark-primary-text,
300: $dark-primary-text,
400: $dark-primary-text,
500: $dark-primary-text,
600: $light-primary-text,
700: $light-primary-text,
800: $light-primary-text,
900: $light-primary-text,
),
);
$night-palette: (
50: #f8fafc,
100: #f1f5f9,
200: #e2e8f0,
300: #cbd5e1,
400: #94a3b8,
500: #64748b,
600: #475569,
700: #334155,
800: #1e293b,
900: #0f172a,
contrast: (
50: $dark-primary-text,
100: $dark-primary-text,
200: $dark-primary-text,
300: $light-primary-text,
400: $light-primary-text,
500: $light-primary-text,
600: $light-primary-text,
700: $light-primary-text,
800: $light-primary-text,
900: $light-primary-text,
),
);
// Background palette for light themes.
$light-theme-background-palette: (
status-bar: map.get($grey-palette, 300),
app-bar: white,
background: map.get($grey-palette, 50),
hover: rgba(#243b53, 0.04),
card: white,
dialog: white,
disabled-button: rgba(#243b53, 0.12),
raised-button: white,
focused-button: $dark-focused,
selected-button: map.get($grey-palette, 300),
selected-disabled-button: map.get($grey-palette, 400),
disabled-button-toggle: map.get($grey-palette, 200),
unselected-chip: map.get($grey-palette, 200),
disabled-list-option: map.get($grey-palette, 200),
tooltip: map.get($grey-palette, 700),
);
// Background palette for dark themes.
$dark-theme-background-palette: (
status-bar: #0b2844,
app-bar: map.get($night-palette, 900),
background: #102a43,
hover: rgba(white, 0.04),
card: map.get($night-palette, 800),
dialog: map.get($night-palette, 800),
disabled-button: rgba(white, 0.12),
raised-button: map.get($night-palette, 800),
focused-button: $light-focused,
selected-button: map.get($night-palette, 900),
selected-disabled-button: map.get($night-palette, 800),
disabled-button-toggle: #243b53,
unselected-chip: map.get($night-palette, 700),
disabled-list-option: #243b53,
tooltip: map.get($night-palette, 700),
);
// Foreground palette for light themes.
$light-theme-foreground-palette: (
base: #243b53,
divider: $dark-dividers,
dividers: $dark-dividers,
disabled: $dark-disabled-text,
disabled-button: rgba(#243b53, 0.26),
disabled-text: $dark-disabled-text,
elevation: #243b53,
hint-text: $dark-disabled-text,
secondary-text: $dark-secondary-text,
icon: rgba(#243b53, 0.54),
icons: rgba(#243b53, 0.54),
text: rgba(#243b53, 0.87),
slider-min: rgba(#243b53, 0.87),
slider-off: rgba(#243b53, 0.26),
slider-off-active: rgba(#243b53, 0.38),
);
// Foreground palette for dark themes.
$dark-theme-foreground-palette: (
base: white,
divider: $light-dividers,
dividers: $light-dividers,
disabled: $light-disabled-text,
disabled-button: rgba(white, 0.3),
disabled-text: $light-disabled-text,
elevation: black,
hint-text: $light-disabled-text,
secondary-text: $light-secondary-text,
icon: white,
icons: white,
text: white,
slider-min: white,
slider-off: rgba(white, 0.3),
slider-off-active: rgba(white, 0.3),
);
theming.scss @use '@angular/material' as mat;
@use 'sass:map';
@use 'globals/_palette';
@function define-light-theme($primary, $accent: null) {
$theme: mat.define-light-theme($primary, $accent);
$color: map.get($theme, color);
$color: map.merge(
$color,
(
background: palette.$light-theme-background-palette,
foreground: palette.$light-theme-foreground-palette,
)
);
@return map.merge(
$theme,
(
color: $color,
)
);
}
@function define-dark-theme($primary, $accent: null) {
$theme: mat.define-dark-theme($primary, $accent);
$color: map.get($theme, color);
$color: map.merge(
$color,
(
background: palette.$dark-theme-background-palette,
foreground: palette.$dark-theme-foreground-palette,
)
);
@return map.merge(
$theme,
(
color: $color,
)
);
}
styles.scss @use '@angular/material' as mat;
@use "globals/theming" as app;
@include mat.core($custom-typography);
// ... primary accent variables
$dark-theme: app.define-dark-theme($dark-primary, $dark-accent);
@include mat.core-theme($dark-theme);
@include mat.button-theme($dark-theme);
@include mat.expansion-theme($dark-theme); And I didn't change any code other than the color palette gray and night. But the end result is the component button and the expansion panel color are still same. Is there anything I missed? |
@arbiyanto that’s because you are using the old/deprecated way to declare a theme. You provide two arguments to your define theme function instead of providing one which should be a theme config. $app-dark-theme: app.define-dark-theme(
(
color: (
primary: $app-primary,
accent: $app-accent,
)
)
); |
@MikaStark I see, thanks for the response! it's working now. |
to mostly reuse the original angular material helper i used this approach to set some colors: // ex. set custom text and secondary text color to css custom properties variant
// add this after mat.define-light-theme or mat.define-dark-theme and before emitting any component-themes
$custom-theme: map.set($custom-theme, color, foreground, text, var(--text-color));
$custom-theme: map.set($custom-theme, color, foreground, secondary-text, var(--secondary-text-color)); |
One solution that I found works perfectly and is easy to understand and use is using
|
I still have this issue. Themed Angular Material with |
After days of digging, I finally found @MikaStark's reply. Thanks @MikaStark! At least it would be great if his answer would be mentioned in the official docs. |
The answer of @MikaStark don't work for and the primary color text it's still black. |
@Alessandroinfo this is an known issue of MDC migration (cf. #26056) that is not related to this issue. The solution I proposed is working. |
@MikaStark I tried that here but don't work. |
According to your code, you don’t override anything and as I said in my previous post, there is a known issue about contrast colors and buttons. I’m afraid that you are out of this issue scope. |
…eground to color object While declaring the primary, accent and warn via the color object is easy and straight-forward, the configuration of foreground and background proves rather tedious. This commit adds the ability to declare foreground and background in the color object when defining a theme, even partially, meaning that missing values are taken from the default light or dark theme respectively. Fixes angular#11390, angular#6244
…eground to color object While declaring the primary, accent and warn via the color object is easy and straight-forward, the configuration of foreground and background proves rather tedious. This commit adds the ability to declare foreground and background in the color object when defining a theme, even partially, meaning that missing values are taken from the default light or dark theme respectively. This commit fixes some possible NPEs in _theming.scss Fixes angular#11390, angular#6244
@MikaStark i reverted the edit. I've modified the theme like your answer but after i cannot see any color in my material component. As a soon i can I'll edit again and let you see. |
using your approach, how we can change the color of a |
Thanks @ibrcic for your great idea, which works. |
There is a schematic for custom themes. Also with the addition of #29363 in v19, you will be able to override theme values system values with the |
Bug, feature request, or proposal:
proposal
What is the expected behavior?
Add documentation on how to set background in a custom theme to https://material.angular.io/guide/theming
What is the current behavior?
No docs
What are the steps to reproduce?
https://material.angular.io/guide/theming
Providing a Plunker (or similar) is the best way to get the team to see your issue.
Plunker template: https://goo.gl/DlHd6U
What is the use-case or motivation for changing an existing behavior?
Makes it easier to customise themes
Which versions of Angular, Material, OS, TypeScript, browsers are affected?
Is there anything else we should know?
The text was updated successfully, but these errors were encountered: