by Charlee Li
通過李李
如何在Angular Material中制作自定義主題 (How to make a custom theme in Angular Material)
Angular Material is a great library that implements Material Design for Angular 2+. The official document is sufficient regarding the component usages, while there are few articles about how to customize the theme itself, specifically, the colors used in the theme.
Angular Material是一個很棒的庫,可實現Angular 2+的Material Design 。 關于組件用法的官方文檔就足夠了,而關于如何自定義主題本身(特別是主題中使用的顏色)的文章很少。
In this post I would like to summarize what I’ve learned these months from customizing Angular Material themes.
在這篇文章中,我想總結一下這幾個月來我從定制Angular Material主題中學到了什么。
Note this article is NOT about AngularJS Material, which is used for AngularJS 1.x.
請注意,本文與用于AngularJS 1.x的 AngularJS材質 無關 。
相關文章 (Related Posts)
Some common posts about customizing themes are:
有關定制主題的一些常見文章是:
“Theming your Angular Material app”, the official guide for custom themes,
自定義主題的官方指南“ 主題化您的Angular Material應用 ”,
“The complete guide to Angular Material Themes” by Tomas Trajan, which provides many undocumented instructions. Strongly recommended.
Tomas Trajan 撰寫的 “ Angular Material Themes完整指南 ”,其中提供了許多未記錄的說明。 強烈推薦 。
I didn’t find other useful posts and would appreciate if anyone could provide some resources in the comments.
我沒有找到其他有用的帖子,如果有人可以在評論中提供一些資源,我將不勝感激。
如何創建自定義主題 (How to Create a Custom Theme)
Creating a material theme is extremely simple: you only need to pick three colors — primary, accent, and warn — and Angular Material will do the rest for you. The material palette page explains how it works clearly, and you can also create a theme visually with Color Tool.
創建材質主題非常簡單:您只需選擇三種顏色( 主色, 強調色和警告色),而Angular Material會為您完成其余工作。 材質調色板頁面說明了其清晰的工作原理,您還可以使用Color Tool直觀地創建主題。
In regards to code, all you need to do is to create the following theme file:
關于代碼,您需要做的就是創建以下主題文件:
// theme.scss@import '~@angular/material/theming';
$my-theme-primary: mat-palette($mat-green);$my-theme-accent : mat-palette($mat-amber);$my-theme-warn : mat-palette($mat-red);
$my-theme: mat-light-theme( $my-theme-primary, $my-theme-accent, $my-theme-warn);
Then you need to apply this theme in your main style.scss
file:
然后,您需要在主style.scss
文件中應用此主題:
@import "theme.scss";
@include mat-core();@include angular-material-theme($my-theme);
如何在組件中使用自定義主題 (How to Use Custom Theme in Components)
After creating our own theme, requirements like this will rise:
創建我們自己的主題后,將產生如下要求:
I want to create a text box. The text color, background color, and border color should all come from our own theme, not by hard coding.
我想創建一個文本框。 文字顏色,背景顏色和邊框顏色都應來自我們自己的主題,而不是硬編碼。
This requirement is pretty common — anyway, being able to be used in components is exactly why we want to create a custom theme. The problem is how.
這項要求很常見-無論如何,能夠在組件中使用正是我們想要創建自定義主題的原因。 問題是如何。
混合方法 (The mixin approach)
The first official document I shared proposed a way of using SCSS’s mixin. I call it a “bottom-up” approach, which includes the following steps:
我共享的第一份正式文檔提出了一種使用SCSS的mixin的方法。 我稱之為“自下而上”的方法,其中包括以下步驟:
Each component defines a theme mixin, and retrieves colors from
$theme
parameter.每個組件都定義一個主題混合,并從
$theme
參數檢索顏色。A global
theme.scss
defines the custom theme, then includes all the component theme mixins and calls them with the custom theme.全局
theme.scss
定義了自定義主題,然后包括所有組件主題mixins并使用自定義主題對其進行調用。
In addition to the theme.scss
definition mentioned above, each component needs to create a theme file like this:
除了上面提到的theme.scss
定義外,每個組件還需要創建一個主題文件,如下所示:
// src/app/comp-a/comp-a.theme.scss@import '~@angular/material/theming';
@mixin comp-a-theme($theme) { // define mixin $primary: map-get($theme, primary); // retrieve color def button { // apply theme to component background-color: mat-color($primary); }}
And probably you want a custom-theme.scss
to import all the component level themes:
可能您希望custom-theme.scss
導入所有組件級主題:
// src/app/custom-theme.scss@import '~@angular/material/theming';@import 'src/app/comp-a/comp-a.theme';@import 'src/app/comp-b/comp-b.theme';
@mixin custom-themes($theme) { @include comp-a-theme($theme); @include comp-b-theme($theme);}
Then import the above custom-theme.scss
in your theme.scss
:
然后將上面的custom-theme.scss
導入您的theme.scss
:
// theme.scss...@import './custom-theme';@include custom-themes($my-theme);
This hierarchy works, and probably is the only way when you need to support multiple themes.
這種層次結構有效,并且可能是您需要支持多個主題的唯一方法。
However, most of the time we only support one theme, and using a mixin could be cumbersome. Mainly there are three disadvantages with this approach:
但是,大多數時候我們只支持一個主題,使用mixin可能很麻煩。 這種方法主要存在三個缺點:
Every single color reference needs a separate
.theme.scss
file.每個單色參考都需要一個單獨的
.theme.scss
文件。custom-theme.scss
must know exactly which components provide custom themes. This creates unnecessary dependencies.custom-theme.scss
必須準確知道哪些組件提供了自定義主題。 這將創建不必要的依賴關系。- Most importantly, component level theme files are not encapsulated. 最重要的是,未封裝組件級主題文件。
The first and second points are pretty self-explanatory. Let me explain a little bit about point 3. This involves some background knowledge called “View Encapsulation”.
第一點和第二點很不言而喻。 讓我對點3進行一些解釋。這涉及一些稱為“視圖封裝”的背景知識。
Angular uses a technique called “View Encapsulation” to keep component CSS local. In other words, rules defined for one component will stay in that component and will not affect other components.
Angular使用一種稱為“ 視圖封裝 ”的技術將組件CSS保持在本地 。 換句話說,為一個組件定義的規則將保留在該組件中,并且不會影響其他組件。
In this way you can define CSS class name freely in your component without worrying about naming conflicts. However, view encapsulation is done only if the CSS is defined through @Component
, i.e. @Component({ styleUrls: ['./comp-a.scss'] })
.
這樣,您可以在組件中自由定義CSS類名,而不必擔心命名沖突。 但是,僅在通過@Component
定義CSS的情況下才進行視圖封裝,即@Component({ styleUrls: ['./comp-a.scss'] })
。
As to our custom theme file comp-a.theme.scss
, since it is imported directly by custom-theme.scss
, its rules are not encapsulated so it will apply to all elements on the page. In the example above, I used the following code (which was WRONG!):
至于我們的自定義主題文件comp-a.theme.scss
,由于它是由custom-theme.scss
直接導入的,因此其規則未封裝,因此將適用于頁面上的所有元素。 在上面的示例中,我使用了以下代碼(錯誤!):
@mixin comp-a-theme($theme) { button { ... } // This will apply to ALL buttons!}
But this will apply the style to all the buttons instead of those buttons belonging to comp-a
only. You have to do something like comp-a button
in order to make this work correctly.
但這會將樣式應用于所有按鈕,而不是僅屬于comp-a
的那些按鈕。 您必須執行諸如comp-a button
的操作才能使其正常工作。
直接方法 (The direct approach)
Therefore I propose a better approach. Instead of using a mixin, we let each component include the theme file and use the color definition directly.
因此,我提出了一種更好的方法。 讓每個組件都包括主題文件并直接使用顏色定義,而不是使用mixin。
In this approach, the component theme file will look like this:
用這種方法,組件主題文件將如下所示:
// NOTE: just do this in your regular scss file.// No need to create separate theme file!// src/app/comp-a/comp-a.scss@import 'src/theme.scss';
$primary: map-get($my-theme, primary);button { background-color: mat-color($primary);}
And that’s all.
就這樣。
Let’s see how this works. First, theme related rules are put into the component SCSS file, so no extra component level theme file required. Second, the main theme.scss
does not need to know component level themes (since it does not need to import them), so a simple theme definition is adequate. Third, the component SCSS file is used with @Component
so it is encapsulated correctly, which means we can simply define rules for button
.
讓我們看看它是如何工作的。 首先,將與主題相關的規則放入組件SCSS文件中,因此不需要額外的組件級主題文件。 其次,主theme.scss
不需要知道組件級主題(因為它不需要導入它們),因此簡單的主題定義就足夠了。 第三,組件SCSS文件與@Component
使用,因此它被正確封裝,這意味著我們可以簡單地為button
定義規則。
預定義的主題鍵 (Predefined Theme Keys)
Probably you have noticed the next problem. What are the foreground
, primary
in above theme files ( map-get($my-theme, primary)
)? Are there any other keys I can use?
可能您已經注意到下一個問題。 上面的主題文件( map-get($my-theme, primary)
)中的foreground
, primary
是什么? 我還能使用其他任何鍵嗎?
Well these “keys” refer to different colors defined in the theme. However I could not find any documents explaining these “keys”, so the only way I could find out is to read the source code. (Although it is said that good programmers should read the code, having to read the code is definitely not a good sign for a library.)
這些“鍵”指的是主題中定義的不同顏色。 但是,我找不到解釋這些“鍵”的任何文檔,所以我唯一能找到的方法就是閱讀源代碼 。 (盡管據說好的程序員應該閱讀代碼, 但是必須閱讀代碼絕對不是一個好的庫。)
Open node_modules/@angular/material/_theming.scss
and you will see the definitions for these keys. For future reference, I would like to summarize the keys here.
打開node_modules/@angular/material/_theming.scss
,您將看到這些鍵的定義。 為了將來參考,我想在這里總結一下按鍵。
$theme |- primary |- accent |- warn |- foreground | |- base | |- divider | |- dividers | |- disabled | |- disabled-button | |- disabled-text | |- hint-text | |- secondary-text | |- icon | |- icons | |- text | |- slider-min | |- slider-off | `- slider-off-active |- background | |- status-bar | |- app-bar | |- background | |- hover | |- card | |- dialog | |- disabled-button | |- raised-button | |- focused-button | |- selected-button | |- selected-disabled-button | |- disabled-button-toggle | |- unselected-chip | `- disabled-list-option `- is-dark // bool, whether dark theme or not
For example, if you want to render a disabled text in your component, you may want to use the following code:
例如,如果要在組件中呈現禁用的文本,則可能需要使用以下代碼:
$foreground: map-get($my-theme, foreground);.disabled-text { color: mat-color($foreground, disabled-text);}
Okay these are some lessons I’ve learned from struggling with Angular Material. Hope this post is helpful if you are facing similar problems.
好的,這些是我從Angular Material的努力中學到的教訓。 如果您遇到類似的問題,希望這篇文章對您有所幫助。
翻譯自: https://www.freecodecamp.org/news/how-to-make-a-custom-theme-in-angular-material-d47122a1e361/