组件样式
Component styles
Angular 应用使用标准的 CSS 来设置样式。这意味着你可以把关于 CSS 的那些知识和技能直接用于 Angular 程序中,例如:样式表、选择器、规则以及媒体查询等。
Angular applications are styled with standard CSS. That means you can apply everything you know about CSS stylesheets, selectors, rules, and media queries directly to Angular applications.
另外,Angular 还能把组件样式捆绑在组件上,以实现比标准样式表更加模块化的设计。
Additionally, Angular can bundle component styles with components, enabling a more modular design than regular stylesheets.
本章将会讲解如何加载和使用这些组件样式。
This page describes how to load and apply these component styles.
你可以运行
You can run the
使用组件样式
Using component styles
对你编写的每个 Angular 组件来说,除了定义 HTML 模板之外,还要定义用于模板的 CSS 样式、 指定任意的选择器、规则和媒体查询。
For every Angular component you write, you may define not only an HTML template, but also the CSS styles that go with that template, specifying any selectors, rules, and media queries that you need.
实现方式之一,是在组件的元数据中设置 styles
属性。 styles
属性可以接受一个包含 CSS 代码的字符串数组。 通常你只给它一个字符串就行了,如同下例:
One way to do this is to set the styles
property in the component metadata. The styles
property takes an array of strings that contain CSS code. Usually you give it one string, as in the following example:
@Component({
selector: 'app-root',
template: `
<h1>Tour of Heroes</h1>
<app-hero-main [hero]="hero"></app-hero-main>
`,
styles: ['h1 { font-weight: normal; }']
})
export class HeroAppComponent {
/* . . . */
}
范围化的样式
Style scope
在 @Component
的元数据中指定的样式只会对该组件的模板生效。
The styles specified in @Component
metadata apply only within the template of that component.
它们既不会被模板中嵌入的组件继承,也不会被通过内容投影(如 ng-content)嵌进来的组件继承。
They are not inherited by any components nested within the template nor by any content projected into the component.
在这个例子中,h1
的样式只对 HeroAppComponent
生效,既不会作用于内嵌的 HeroMainComponent
,也不会作用于应用中其它任何地方的 <h1>
标签。
In this example, the h1
style applies only to the HeroAppComponent
, not to the nested HeroMainComponent
nor to <h1>
tags anywhere else in the application.
这种范围限制就是所谓的样式模块化特性
This scoping restriction is a styling modularity feature.
可以使用对每个组件最有意义的 CSS 类名和选择器。
You can use the CSS class names and selectors that make the most sense in the context of each component.
类名和选择器是局限于该组件的,它不会和应用中其它地方的类名和选择器冲突。
Class names and selectors are local to the component and don't collide with classes and selectors used elsewhere in the application.
组件的样式不会因为别的地方修改了样式而被意外改变。
Changes to styles elsewhere in the application don't affect the component's styles.
你可以让每个组件的 CSS 代码和它的 TypeScript、HTML 代码放在一起,这将促成清爽整洁的项目结构。
You can co-locate the CSS code of each component with the TypeScript and HTML code of the component, which leads to a neat and tidy project structure.
将来你可以修改或移除组件的 CSS 代码,而不用遍历整个应用来看它有没有在别处用到。
You can change or remove component CSS code without searching through the whole application to find where else the code is used.
特殊的选择器
Special selectors
组件样式中有一些从影子(Shadow) DOM 样式范围领域(记录在W3C的CSS Scoping Module Level 1中) 引入的特殊选择器:
Component styles have a few special selectors from the world of shadow DOM style scoping (described in the CSS Scoping Module Level 1 page on the W3C site). The following sections describe these selectors.
:host
使用 :host
伪类选择器,用来选择组件宿主元素中的元素(相对于组件模板内部的元素)。
Use the :host
pseudo-class selector to target styles in the element that hosts the component (as opposed to targeting elements inside the component's template).
:host {
display: block;
border: 1px solid black;
}
:host
选择是是把宿主元素作为目标的唯一方式。除此之外,你将没办法指定它, 因为宿主不是组件自身模板的一部分,而是父组件模板的一部分。
The :host
selector is the only way to target the host element. You can't reach the host element from inside the component with other selectors because it's not part of the component's own template. The host element is in a parent component's template.
要把宿主样式作为条件,就要像函数一样把其它选择器放在 :host
后面的括号中。
Use the function form to apply host styles conditionally by including another selector inside parentheses after :host
.
下一个例子再次把宿主元素作为目标,但是只有当它同时带有 active
CSS 类的时候才会生效。
The next example targets the host element again, but only when it also has the active
CSS class.
:host(.active) {
border-width: 3px;
}
:host
选择器也可以与其他选择器组合使用。在 :host
后面添加选择器以选择子元素,例如,使用 :host h2
定位组件视图内的 <h2>
。
The :host
selector can also be combined with other selectors. Add selectors behind the :host
to select child elements, for example using :host h2
to target all <h2>
elements inside a component's view.
不应该在 :host
选择器前面添加除 :host-context
之外的选择器来试图基于组件视图的外部上下文为本组件设置样式。因为此类选择器的作用域不会限于组件的视图,而是会选择外部上下文,但这不是自然的行为。请改用 :host-context
选择器。
You should not add selectors (other than :host-context
) in front of the :host
selector to style a component based on the outer context of the component's view. Such selectors are not scoped to a component's view and will select the outer context, but it's not native behavior. Use :host-context
selector for that purpose instead.
:host-context
有时候,基于某些来自组件视图外部的条件应用样式是很有用的。 例如,在文档的 <body>
元素上可能有一个用于表示样式主题 (theme) 的 CSS 类,你应当基于它来决定组件的样式。
Sometimes it's useful to apply styles based on some condition outside of a component's view. For example, a CSS theme class could be applied to the document <body>
element, and you want to change how your component looks based on that.
这时可以使用 :host-context()
伪类选择器。它也以类似 :host()
形式使用。它在当前组件宿主元素的祖先节点中查找 CSS 类, 直到文档的根节点为止。在与其它选择器组合使用时,它非常有用。
Use the :host-context()
pseudo-class selector, which works just like the function form of :host()
. The :host-context()
selector looks for a CSS class in any ancestor of the component host element, up to the document root. The :host-context()
selector is useful when combined with another selector.
在下面的例子中,只有当某个祖先元素有 CSS 类 theme-light
时,才会把 background-color
样式应用到组件内部的所有 <h2>
元素中。
The following example applies a background-color
style to all <h2>
elements inside the component, only if some ancestor element has the CSS class theme-light
.
:host-context(.theme-light) h2 {
background-color: #eef;
}
已弃用 /deep/
、>>>
和 ::ng-deep
(deprecated) /deep/
, >>>
, and ::ng-deep
组件样式通常只会作用于组件自身的 HTML 上。
Component styles normally apply only to the HTML in the component's own template.
把伪类 ::ng-deep
应用到任何一条 CSS 规则上就会完全禁止对那条规则的视图包装。任何带有 ::ng-deep
的样式都会变成全局样式。为了把指定的样式限定在当前组件及其下级组件中,请确保在 ::ng-deep
之前带上 :host
选择器。如果 ::ng-deep
组合器在 :host
伪类之外使用,该样式就会污染其它组件。
Applying the ::ng-deep
pseudo-class to any CSS rule completely disables view-encapsulation for that rule. Any style with ::ng-deep
applied becomes a global style. In order to scope the specified style to the current component and all its descendants, be sure to include the :host
selector before ::ng-deep
. If the ::ng-deep
combinator is used without the :host
pseudo-class selector, the style can bleed into other components.
这个例子以所有的 <h3>
元素为目标,从宿主元素到当前元素再到 DOM 中的所有子元素:
The following example targets all <h3>
elements, from the host element down through this component to all of its child elements in the DOM.
:host ::ng-deep h3 {
font-style: italic;
}
/deep/
组合器还有两个别名:>>>
和 ::ng-deep
。
The /deep/
combinator also has the aliases >>>
, and ::ng-deep
.
/deep/
和 >>>
选择器只能被用在仿真 (emulated) 模式下。 这种方式是默认值,也是用得最多的方式。 更多信息,见控制视图封装模式一节。
Use /deep/
, >>>
and ::ng-deep
only with emulated view encapsulation. Emulated is the default and most commonly used view encapsulation. For more information, see the View Encapsulation section.
CSS 标准中用于 "刺穿 Shadow DOM" 的组合器已经被弃用,并将这个特性从主流浏览器和工具中移除。 因此,我们也将在 Angular 中移除对它们的支持(包括 /deep/
、>>>
和 ::ng-deep
)。 目前,建议先统一使用 ::ng-deep
,以便兼容将来的工具。
The shadow-piercing descendant combinator is deprecated and support is being removed from major browsers and tools. As such we plan to drop support in Angular (for all 3 of /deep/
, >>>
and ::ng-deep
). Until then ::ng-deep
should be preferred for a broader compatibility with the tools.
把样式加载进组件中
Loading component styles
有几种方式把样式加入组件:
There are several ways to add styles to a component:
设置
styles
或styleUrls
元数据By setting
styles
orstyleUrls
metadata.内联在模板的 HTML 中
Inline in the template HTML.
通过 CSS 文件导入
With CSS imports.
上述作用域规则对所有这些加载模式都适用。
The scoping rules outlined earlier apply to each of these loading patterns.
元数据中的样式
Styles in component metadata
你可以给 @Component
装饰器添加一个 styles
数组型属性。
You can add a styles
array property to the @Component
decorator.
这个数组中的每一个字符串(通常也只有一个)定义一份 CSS。
Each string in the array defines some CSS for this component.
@Component({
selector: 'app-root',
template: `
<h1>Tour of Heroes</h1>
<app-hero-main [hero]="hero"></app-hero-main>
`,
styles: ['h1 { font-weight: normal; }']
})
export class HeroAppComponent {
/* . . . */
}
注意:这些样式只对当前组件生效。 它们既不会作用于模板中嵌入的任何组件,也不会作用于投影进来的组件(如 ng-content
)。
Reminder: these styles apply only to this component. They are not inherited by any components nested within the template nor by any content projected into the component.
当使用 --inline-styles
标识创建组件时,Angular CLI 的 ng generate component
命令就会定义一个空的 styles
数组
The Angular CLI command ng generate component
defines an empty styles
array when you create the component with the --inline-style
flag.
ng generate component hero-app --inline-style
组件元数据中的样式文件
Style files in component metadata
你可以通过把外部 CSS 文件添加到 @Component
的 styleUrls
属性中来加载外部样式。
You can load styles from external CSS files by adding a styleUrls
property to a component's @Component
decorator:
@Component({
selector: 'app-root',
template: `
<h1>Tour of Heroes</h1>
<app-hero-main [hero]="hero"></app-hero-main>
`,
styleUrls: ['./hero-app.component.css']
})
export class HeroAppComponent {
/* . . . */
}
注意:这些样式只对当前组件生效。 它们既不会作用于模板中嵌入的任何组件,也不会作用于投影进来的组件(如 ng-content
)。
Reminder: the styles in the style file apply only to this component. They are not inherited by any components nested within the template nor by any content projected into the component.
你可以指定多个样式文件,甚至可以组合使用 style
和 styleUrls
方式。
You can specify more than one styles file or even a combination of styles
and styleUrls
.
当你使用 Angular CLI 的 ng generate component
命令但不带 --inline-style
标志时,CLI 会为你创建一个空白的样式表文件,并且在所生成组件的 styleUrls
中引用该文件。
When you use the Angular CLI command ng generate component
without the --inline-style
flag, it creates an empty styles file for you and references that file in the component's generated styleUrls
.
ng generate component hero-app
模板内联样式
Template inline styles
你也可以直接在组件的 HTML 模板中写 <style>
标签来内嵌 CSS 样式。
You can embed CSS styles directly into the HTML template by putting them inside <style>
tags.
@Component({
selector: 'app-hero-controls',
template: `
<style>
button {
background-color: white;
border: 1px solid #777;
}
</style>
<h3>Controls</h3>
<button (click)="activate()">Activate</button>
`
})
模板中的 link 标签
Template link tags
你也可以在组件的 HTML 模板中写 <link>
标签。
You can also write <link>
tags into the component's HTML template.
@Component({
selector: 'app-hero-team',
template: `
<!-- We must use a relative URL so that the AOT compiler can find the stylesheet -->
<link rel="stylesheet" href="../assets/hero-team.component.css">
<h3>Team</h3>
<ul>
<li *ngFor="let member of hero.team">
{{member}}
</li>
</ul>`
})
当使用 CLI 进行构建时,要确保这个链接到的样式表文件被复制到了服务器上。参阅资产文件配置指南。
When building with the CLI, be sure to include the linked style file among the assets to be copied to the server as described in the Assets configuration guide.
只要引用过,CLI 就会计入这个样式表,无论这个 link 标签的 href 指向的 URL 是相对于应用根目录的还是相对于组件文件的。
Once included, the CLI will include the stylesheet, whether the link tag's href URL is relative to the application root or the component file.
CSS @imports 语法
CSS @imports
你还可以利用标准的 CSS @import
规则来把其它 CSS 文件导入到 CSS 文件中。
You can also import CSS files into the CSS files using the standard CSS @import
rule. For details, see @import
on the MDN site.
在这种情况下,URL 是相对于你正在导入的 CSS 文件的。
In this case, the URL is relative to the CSS file into which you're importing.
/* The AOT compiler needs the `./` to show that this is local */
@import './hero-details-box.css';
外部以及全局样式文件
External and global style files
当使用 CLI 进行构建时,你必须配置 angular.json
文件,使其包含所有外部资源(包括外部的样式表文件)。
When building with the CLI, you must configure the angular.json
to include all external assets, including external style files.
在它的 styles
区注册这些全局样式文件,默认情况下,它会有一个预先配置的全局 styles.css
文件。
Register global style files in the styles
section which, by default, is pre-configured with the global styles.css
file.
要了解更多,参阅 样式配置指南。
See the Styles configuration guide to learn more.
非 CSS 样式文件
Non-CSS style files
如果使用 CLI 进行构建,那么你可以用 sass、less 或 stylus 来编写样式,并使用相应的扩展名(.scss
、.less
、.styl
)把它们指定到 @Component.styleUrls
元数据中。例子如下:
If you're building with the CLI, you can write style files in sass, less, or stylus and specify those files in the @Component.styleUrls
metadata with the appropriate extensions (.scss
, .less
, .styl
) as in the following example:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
...
CLI 的构建过程会运行相关的预处理器。
The CLI build process runs the pertinent CSS preprocessor.
当使用 ng generate component
命令生成组件文件时,CLI 会默认生成一个空白的 CSS 样式文件(.css
)。 你可以配置 CLI,让它默认使用你喜欢的 CSS 预处理器,参阅工作区配置指南中的解释。
When generating a component file with ng generate component
, the CLI emits an empty CSS styles file (.css
) by default. You can configure the CLI to default to your preferred CSS preprocessor as explained in the Workspace configuration guide.
添加到 @Component.styles
数组中的字符串必须写成 CSS,因为 CLI 没法对这些内联的样式使用任何 CSS 预处理器。
Style strings added to the @Component.styles
array must be written in CSS because the CLI cannot apply a preprocessor to inline styles.