Skip to content

Commit 9490c90

Browse files
authored
docs: clarify points to address common issues (#4021)
* Repeated reminders to only include mat-core once. * Note about including a theme file via styleUrls * Add section for theming only certain components * Move section on overlay theming after section for multiple themes
1 parent b1e31bd commit 9490c90

File tree

1 file changed

+113
-32
lines changed

1 file changed

+113
-32
lines changed

guides/theming.md

+113-32
Original file line numberDiff line numberDiff line change
@@ -50,35 +50,27 @@ Finally, if your app's content **is not** placed inside of a `md-sidenav-contain
5050
need to add the `mat-app-background` class to your wrapper element (for example the `body`). This
5151
ensures that the proper theme background is applied to your page.
5252

53-
#### Theming overlay-based components
54-
Since certain components (e.g. `dialog`) are inside of a global overlay container, your theme may
55-
not be applied to them. In order to define the theme that will be used for overlay components, you
56-
have to specify it on the global `OverlayContainer` instance:
57-
58-
```ts
59-
import {OverlayContainer} from '@angular/material';
60-
61-
@NgModule({
62-
// misc config goes here
63-
})
64-
export class YourAppModule {
65-
constructor(overlayContainer: OverlayContainer) {
66-
overlayContainer.themeClass = 'your-theme';
67-
}
68-
}
69-
```
70-
7153
### Defining a custom theme
7254
When you want more customization than a pre-built theme offers, you can create your own theme file.
7355

74-
A theme file is a simple Sass file that defines your palettes and passes them to mixins that output
75-
the corresponding styles. A typical theme file will look something like this:
56+
A custom theme file does two things:
57+
1. Imports the `mat-core()` sass mixin. This includes all common styles that are used by multiple
58+
components. **This should only be included once in your application.** If this mixin is included
59+
multiple times, your application will end up with multiple copies of these common styles.
60+
2. Defines a **theme** data structure as the composition of multiple palettes. This object can be
61+
created with either the `mat-light-theme` function or the `mat-dark-theme` function. The output of
62+
this function is then passed to the `angular-material-theme` mixin, which will output all of the
63+
corresponding styles for the theme.
64+
65+
66+
A typical theme file will look something like this:
7667
```scss
7768
@import '~@angular/material/theming';
7869
// Plus imports for other components in your app.
7970

80-
// Include the base styles for Angular Material core. We include this here so that you only
71+
// Include the common styles for Angular Material. We include this here so that you only
8172
// have to load a single css file for Angular Material in your app.
73+
// Be sure that you only ever include this mixin once!
8274
@include mat-core();
8375

8476
// Define the palettes for your theme using the Material Design palettes available in palette.scss
@@ -110,28 +102,117 @@ as gulp-sass or grunt-sass). The simplest approach is to use the `node-sass` CLI
110102
```
111103
node-sass src/unicorn-app-theme.scss dist/unicorn-app-theme.css
112104
```
113-
and then include the output file in your application.
105+
and then include the output file in your index.html.
106+
107+
The theme file **should not** be imported into other SCSS files. This will cause duplicate styles
108+
to be written into your CSS output. If you want to consume the theme definition object
109+
(e.g., `$candy-app-theme`) in other SCSS files, then the definition of the theme object should be
110+
broken into its own file, separate from the inclusion of the `mat-core` and
111+
`angular-material-theme` mixins.
114112

115113
The theme file can be concatenated and minified with the rest of the application's css.
116114

115+
Note that if you include the generated theme file in the `styleUrls` of an Angular component, those
116+
styles will be subject to that component's [view encapsulation](https://angular.io/docs/ts/latest/guide/component-styles.html#!#view-encapsulation).
117+
117118
#### Multiple themes
118-
You can extend the example above to define a second (or third or fourth) theme that is gated by
119-
some selector. For example, we could append the following to the example above to define a
120-
secondary dark theme:
119+
You can create multiple themes for your application by including the `angular-material-theme` mixin
120+
multiple times, where each inclusion is gated by an additional CSS class.
121+
122+
Remember to only ever include the `@mat-core` mixin only once; it should not be included for each
123+
theme.
124+
125+
##### Example of defining multiple themes:
121126
```scss
122-
.unicorn-dark-theme {
123-
$dark-primary: mat-palette($mat-blue-grey);
124-
$dark-accent: mat-palette($mat-amber, A200, A100, A400);
125-
$dark-warn: mat-palette($mat-deep-orange);
127+
@import '~@angular/material/theming';
128+
// Plus imports for other components in your app.
129+
130+
// Include the common styles for Angular Material. We include this here so that you only
131+
// have to load a single css file for Angular Material in your app.
132+
// **Be sure that you only ever include this mixin once!**
133+
@include mat-core();
134+
135+
// Define the default theme (same as the example above).
136+
$candy-app-primary: mat-palette($mat-indigo);
137+
$candy-app-accent: mat-palette($mat-pink, A200, A100, A400);
138+
$candy-app-theme: mat-light-theme($candy-app-primary, $candy-app-accent);
139+
140+
// Include the default theme styles.
141+
@include angular-material-theme($candy-app-theme);
126142

127-
$dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn);
128143

144+
// Define an alternate dark theme.
145+
$dark-primary: mat-palette($mat-blue-grey);
146+
$dark-accent: mat-palette($mat-amber, A200, A100, A400);
147+
$dark-warn: mat-palette($mat-deep-orange);
148+
$dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn);
149+
150+
// Include the alternative theme styles inside of a block with a CSS class. You can make this
151+
// CSS class whatever you want. In this example, any component inside of an element with
152+
// `.unicorn-dark-theme` will be affected by this alternate dark theme instead of the default theme.
153+
.unicorn-dark-theme {
129154
@include angular-material-theme($dark-theme);
130155
}
131156
```
132157

133-
With this, any element inside of a parent with the `unicorn-dark-theme` class will use this
134-
dark theme.
158+
In the above example, any component inside of a parent with the `unicorn-dark-theme` class will use
159+
the dark theme, while other components will fall back to the default `$candy-app-theme`.
160+
161+
You can include as many themes as you like in this manner. You can also `@include` the
162+
`angular-material-theme` in separate files and then lazily load them based on an end-user
163+
interaction (how to lazily load the CSS assets will vary based on your application).
164+
165+
It's important to remember, however, that the `mat-core` mixin should only ever be included _once_.
166+
167+
##### Multiple themes and overlay-based components
168+
Since certain components (e.g. `dialog`) are inside of a global overlay container, the css class
169+
that determines the theme (such as the `.unicorn-dark-theme` example above), an additional step is
170+
needed to affect overlay-based components (menu, select, dialog, etc.).
171+
172+
To do this, you can specify a `themeClass` on the global overlay container. For the example above,
173+
this would look like:
174+
```ts
175+
import {OverlayContainer} from '@angular/material';
176+
177+
@NgModule({
178+
// ...
179+
})
180+
export class UnicornCandyAppModule {
181+
constructor(overlayContainer: OverlayContainer) {
182+
overlayContainer.themeClass = 'unicorn-dark-theme';
183+
}
184+
}
185+
```
186+
187+
The `themeClass` of the `OverlayContainer` can be changed at any time to change the active theme
188+
class.
189+
190+
#### Theming only certain components
191+
The `angular-material-theme` mixin will output styles for [all components in the library](https://github.com/angular/material2/blob/master/src/lib/core/theming/_all-theme.scss).
192+
If you are only using a subset of the components (or if you want to change the theme for specific
193+
components), you can include component-specific theme mixins. You also will need to include
194+
the `mat-core-theme` mixin as well, which contains theme-specific styles for common behaviors
195+
(such as ripples).
196+
197+
```scss
198+
@import '~@angular/material/theming';
199+
// Plus imports for other components in your app.
200+
201+
// Include the common styles for Angular Material. We include this here so that you only
202+
// have to load a single css file for Angular Material in your app.
203+
// **Be sure that you only ever include this mixin once!**
204+
@include mat-core();
205+
206+
// Define the theme.
207+
$candy-app-primary: mat-palette($mat-indigo);
208+
$candy-app-accent: mat-palette($mat-pink, A200, A100, A400);
209+
$candy-app-theme: mat-light-theme($candy-app-primary, $candy-app-accent);
210+
211+
// Include the theme styles for only specified components.
212+
@include mat-core-theme($theme);
213+
@include mat-button-theme($theme);
214+
@include mat-checkbox-theme($theme);
215+
```
135216

136217
### Theming your own components
137218
For more details about theming your own components,

0 commit comments

Comments
 (0)