Angular应用程序使用标准CSS进行样式化。 这意味着您可以将所有关于CSS样式表,选择器,规则和媒体查询的知识直接应用于Angular应用程序。
此外,Angular可以将组件样式与组件捆绑在一起,从而实现比常规样式表更多的模块化设计。
本页介绍如何加载和应用这些组件样式。
使用组件样式
对于您编写的每个Angular组件,您不仅可以定义HTML模板,还可以定义与该模板一起使用的CSS样式,指定您需要的任何选择器,规则和媒体查询。
一种方法是在组件元数据中设置styles属性。 styles属性采用包含CSS代码的字符串列表。 通常你给它一个字符串,如下例所示:lib/app_component.dart
@Component(
selector: 'hero-app',
template: '''
<h1>Tour of Heroes</h1>
<hero-app-main [hero]="hero"></hero-app-main>''',
styles: const ['h1 { font-weight: normal; }'],
directives: const [HeroAppMainComponent])
class AppComponent {
// ···
}
您放入组件样式中的选择器仅适用于该组件中的模板。 上例中的h1选择器仅适用于HeroAppComponent模板中的<h1>标记。 应用中其他地方的任何<h1>元素都不受影响。
与传统的CSS工作方式相比,这是模块化方面的重大改进。
- 您可以在每个组件的上下文中使用最有意义的CSS类名称和选择器。
- 类名和选择器是组件本地的,不会与应用程序中其他地方使用的类和选择器相冲突。
- 应用程序中其他位置的样式更改不会影响组件的样式。
- 您可以将每个组件的CSS代码与组件的Dart和HTML代码共同定位,从而生成整洁的项目结构。
- 您可以更改或删除组件CSS代码,而无需搜索整个应用程序以查找代码的使用位置。
特殊选择器
组件样式有一些取于DOM样式范围中的特殊选择器(在W3C站点的CSS范围模块1级页面中描述)。
:host
使用:host伪类选择器来定位承载组件的元素中的样式(而不是定位组件模板中的元素)。
lib/src/hero_details_component.css (host)
:host {
display: block;
border: 1px solid black;
}
:host选择器是定位宿主元素的唯一方法。您不能使用其他选择器从组件内部到达宿主元素,因为它不是组件自己的模板的一部分。宿主元素位于父组件的模板中。
通过在:host之后的括号中包含另一个选择器使用函数形式有条件地应用宿主样式
下一个示例再次定位主机元素,但仅限于它还具有activeCSS类。
lib/src/hero_details_component.css (host function)
:host(.active) {
border-width: 3px;
}
:host-context
有时候,根据组件视图之外的某些条件来应用样式会很有用。例如,一个CSS主题类可以应用于文档<body>元素,并且你想改变你的组件看起来如何基于这个。
使用:host-context()伪类选择器,它的作用就像:host()的函数形式一样。:host-context()选择器在组件宿主元素的任意祖先中查找CSS类,直到文档根。当与另一个选择器组合时,:host-contex()选择器很有用。
以下示例仅在某个祖先元素具有CSS类theme-light的情况下,才会将background-color样式应用于组件内的所有<h2>元素。
lib/src/hero_details_component.css (host-context)
:host-context(.theme-light) h2 {
background-color: #eef;
}
::ng-deep
组件样式通常仅适用于组件自己的模板中的HTML。
使用::ng-deep选择器可以通过子组件树强制一个样式到所有的子组件视图。::ng-deep选择器适用于嵌套组件的任何深度,并且适用于组件的视图子组件和内容子组件。
以下示例将所有<h3>元素作为目标,从宿主元素向下到这个组件到它的所有子元素。
lib/src/hero_details_component.css (deep)
:host ::ng-deep h3 {
font-style: italic;
}
仅在模拟视图封装中使用::ng-deep选择器.模拟是默认和最常用的视图封装。有关更多信息,请参阅控制视图封装部分。
加载样式到组件
这里有几种加载样式到组件的方法:
- 通过设置styles或styleUrls元数据.
- HTML模板内链样式.
- CSS导入.
作用规则条例早期适用于每个加载模式.
元数据中使用Styles
可以添加一个styles列表属性到@Component注解. 列表中的每一个(通常只有一个字符串) 定义CSS. lib/app_component.dart
@Component(
selector: 'hero-app',
template: '''
<h1>Tour of Heroes</h1>
<hero-app-main [hero]="hero"></hero-app-main>''',
styles: const ['h1 { font-weight: normal; }'],
directives: const [HeroAppMainComponent])
class AppComponent {
// ···
}
元数据中使用Style URLs
可以通过添加一个styleUrls属性到组件的@Component 注解从外部CSS文件加载样式:
lib/src/hero_details_component.dart (styleUrls)
@Component(
selector: 'hero-details',
template: '''
<h2>{{hero.name}}</h2>
<hero-team [hero]="hero"></hero-team>
<ng-content></ng-content>''',
styleUrls: const ['hero_details_component.css'],
directives: const [HeroTeamComponent])
class HeroDetailsComponent {
// ···
}
注意styleUrls中的URLs与组件是相对路径.
模板内联样式
可以枚举样式到HTML模板通过放置他们到<style>标签内部.
lib/src/hero_controls_component.dart (inline styles)
@Component(
selector: 'hero-controls',
template: '''
<style>
button {
background-color: white;
border: 1px solid #777;
}
</style>
<h3>Controls</h3>
<button (click)="activate()">Activate</button>''')
class HeroControlsComponent {
@Input()
Hero hero;
void activate() {
hero.active = true;
}
}
模板link标签
你可以枚举<link>标签到组件的HTML 模板.
<link>标签的href URL相对于应用根路径, 而不是组件文件.
lib/src/hero_team_component.dart (stylesheet link)
@Component(
selector: 'hero-team',
template: '''
<link rel="stylesheet" href="hero_team_component.css">
<h3>Team</h3>
<ul>
<li *ngFor="let member of hero.team">
{{member}}
</li>
</ul>''',
directives: const [CORE_DIRECTIVES],
)
class HeroTeamComponent {
@Input()
Hero hero;
}
CSS @imports
你可以使用标准CSS @import规则导入CSS文件到CSS文件. 详情, 在MDN站点查看@import
这个例子中的URL与CSS 文件是相对路径.
lib/src/hero_details_component.css (excerpt)
@import 'hero_details_box.css';
封装控制视图:native,emulated,和none
如早期讨论的一样, 组件 CSS 样式封装到组件视图 并且不影响应用程序的其它部分.
控制每个组件底层之上封装如何发生, 你可以在组件元数据里设置 视图封装模型. 从下列模式中选择:
- Native视图封装 使用了浏览器的原生shadow DOM实现 (查看Shadow DOM在MDN站点上) 附加一个shadow DOM到组件的宿主元素上, 并且将组件视图放入shadow DOM内. 组件的样式包含在shadow DOM内.
- Emulated视图封装 (默认) 仿真shadow DOM的行为通过预处理 (和重命名)CSS代码到有效的CSS到组件视图. 更多信息, 查看附录1.
- None意味着Angular没有视图封装. Angular添加CSS 到全局样式. 作用域规则, 隔离, 和保护的早期论述不会被应用. 本质上与粘贴组件的样式到HTML一致.
设置组件封装模型,使用组件元数据中的encapsulation属性:
lib/src/quest_summary_component.dart (native encapsulation)
// warning: few browsers support shadow DOM encapsulation at this time
encapsulation: ViewEncapsulation.Native
Native视图封装仅仅在浏览器原生支持shadow DOM ( 在Can I use站点查看Shadow DOM v0)时有效. 支持仍然有限, 那就是为什么Emulated视图封装是默认的模型并且在大多数例子中被推荐.
附录 1: 检查在emulated视图封装模型产生的CSS
当使用emulated视图封装时, Angular预处理所有组件样式以致接近标准shadow CSS 作用域规则.
使用emulated视图封装的处于运行状态的Angular应用中的DOM, 每一个DOM元素都有额外的类附加在上面:
<hero-details class="_nghost-pmm-5">
<h2 class="_ngcontent-pmm-5">Mister Fantastic</h2>
<hero-team class="_ngcontent-pmm-5 _nghost-pmm-6">
<h3 class="_ngcontent-pmm-6">Team</h3>
</hero-team>
</hero-detail>
这里有两种生成的类:
- 一个元素将成为shadow DOM 宿主在原生封装中 生成的 _nghost 类. 这是组件宿主元素的一般实例.
- 在组件视图里的元素有一个_ngcontent 类 用来标识这个元素属于模仿哪一个宿主的shadow DOM.
这些类的精确值是不重要的. 它们是自动生成的并且你未在应用代码中涉及到. 但它们通过生成的组件样式被定向,在DOM中的<head>区块 :
._nghost-pmm-5 {
display: block;
border: 1px solid black;
}
h3._ngcontent-pmm-6 {
background-color: white;
border: 1px solid #777;
}
这些样式是后处理的以便每个选择器使用_nghost或_ngcontent类选择器来增强. 这些额外的选择器使作用域规则可以在此页面描述.
附录2: 使用相对路径的URLs加载样式
通常惯例是分割组件的代码、CSS和HTML到同一目录下的三个分离文件中:
- quest_summary_component.dart
- quest_summary_component.html
- quest_summary_component.css
你可以通过设置独自的templateUrl和styleUrls元数据属性来包含CSS和模板文件. 因为这些文件与组件本地协作, 通过名字引用它们是非常不错的 除此而外也可以指定一个路径返回到应用的根.
感激的是, 这是在AngularDart相对定位URLs中默认解释 :
templateUrl: 'quest_summary_component.html',
styleUrls: const ['quest_summary_component.css'])