对于我们写的每个 Angular 组件来说,除了定义 HTML 模板之外,我们还要定义用于模板的 CSS 样式、 指定任意的选择器、规则和媒体查询。
实现方式之一,是在组件的元数据中设置styles属性。styles属性可以接受一个包含 CSS 代码的字符串数组。 通常我们只给它一个字符串就行了,如同下例:
COPY CODE@Component({ selector: 'hero-app', template: `
Tour of Heroes
组件样式在很多方面都不同于传统的全局性样式。
首先,我们放在组件样式中的选择器,只会应用在组件自身的模板中。上面这个例子中的h1选择器只会对HeroAppComponent模板中的
标签生效,而对应用中其它地方的
元素毫无影响。
这种模块化相对于 CSS 的传统工作方式是一个巨大的改进:
可以使用对每个组件最有意义的 CSS 类名和选择器。
类名和选择器是仅属于组件内部的,它不会和应用中其它地方的类名和选择器出现冲突。
我们组件的样式不会因为别的地方修改了样式而被意外改变。
我们可以让每个组件的 CSS 代码和它的 TypeScript、HTML 代码放在一起,这将促成清爽整洁的项目结构。
将来我们可以修改或移除组件的 CSS 代码,而不用遍历整个应用来看它有没有被别处用到,只要看看当前组件就可以了。
特殊的选择器
组件样式中有一些从影子 DOM 样式范围 (Shadow DOM style scoping)领域引入的特殊选择器:
:host
使用:host伪类选择器,用来选择组件宿主元素中的元素(相对于组件模板内部的元素)。
COPY CODE:host { display: block; border: 1px solid black; }
这是我们能以宿主元素为目标的唯一方式。除此之外,我们将没办法指定它, 因为宿主不是组件自身模板的一部分,而是父组件模板的一部分。
要把宿主样式作为条件,就要像函数一样把其它选择器放在:host后面的括号中。
在下一个例子中,我们又一次把宿主元素作为目标,但是只有当它同时带有activeCSS 类的时候才会生效。
COPY CODE:host(.active) { border-width: 3px; }
:host-context
有时候,基于某些来自组件视图外部的条件应用样式是很有用的。 例如,在文档的
元素上可能有一个用于表示样式主题 (theme) 的 CSS 类,而我们应当基于它来决定组件的样式。这时可以使用:host-context()伪类选择器。它也以类似:host()形式使用。它在当前组件宿主元素的祖先节点中查找 CSS 类, 直到文档的根节点为止。在与其它选择器组合使用时,它非常有用。
在下面的例子中,只有当某个祖先元素有 CSS 类theme-light时,我们才会把background-color样式应用到组件内部的所有
元素中。
COPY CODE:host-context(.theme-light) h2 { background-color: #eef; }
/deep/
组件样式通常只会作用于组件自身的 HTML 上。
我们可以使用/deep/选择器,来强制一个样式对各级子组件的视图也生效,它不但作用于组件的子视图,也会作用于组件的内容。
在这个例子中,我们以所有的
元素为目标,从宿主元素到当前元素再到 DOM 中的所有子元素:
COPY CODE:host /deep/ h3 { font-style: italic; }
/deep/选择器还有一个别名>>>。我们可以任意交替使用它们。
/deep/和>>>选择器只能被用在仿真 (emulated)模式下。 这种方式是默认值,也是用得最多的方式。 更多信息,见控制视图封装模式一节。