|
| 1 | +# Component styles |
| 2 | + |
| 3 | +Angular applications are styled with standard CSS. That means you can apply |
| 4 | +everything you know about CSS stylesheets, selectors, rules, and media queries |
| 5 | +directly to Angular applications. |
| 6 | + |
| 7 | +Additionally, Angular can bundle *component styles* |
| 8 | +with components, enabling a more modular design than regular stylesheets. |
| 9 | + |
| 10 | +This page describes how to load and apply these component styles. |
| 11 | + |
| 12 | +You can run the <live-example></live-example> in Stackblitz and download the code from there. |
| 13 | + |
| 14 | +## Using component styles |
| 15 | + |
| 16 | +For every Angular component you write, you may define not only an HTML template, |
| 17 | +but also the CSS styles that go with that template, |
| 18 | +specifying any selectors, rules, and media queries that you need. |
| 19 | + |
| 20 | +One way to do this is to set the `styles` property in the component metadata. |
| 21 | +The `styles` property takes an array of strings that contain CSS code. |
| 22 | +Usually you give it one string, as in the following example: |
| 23 | + |
| 24 | +<code-example path="component-styles/src/app/hero-app.component.ts" header="src/app/hero-app.component.ts"></code-example> |
| 25 | + |
| 26 | +## Style scope |
| 27 | + |
| 28 | +<div class="alert is-critical"> |
| 29 | + |
| 30 | +The styles specified in `@Component` metadata _apply only within the template of that component_. |
| 31 | + |
| 32 | +</div> |
| 33 | + |
| 34 | +They are _not inherited_ by any components nested within the template nor by any content projected into the component. |
| 35 | + |
| 36 | +In this example, the `h1` style applies only to the `HeroAppComponent`, |
| 37 | +not to the nested `HeroMainComponent` nor to `<h1>` tags anywhere else in the application. |
| 38 | + |
| 39 | +This scoping restriction is a ***styling modularity feature***. |
| 40 | + |
| 41 | +* You can use the CSS class names and selectors that make the most sense in the context of each component. |
| 42 | + |
| 43 | + |
| 44 | +* Class names and selectors are local to the component and don't collide with |
| 45 | + classes and selectors used elsewhere in the application. |
| 46 | + |
| 47 | + |
| 48 | +* Changes to styles elsewhere in the application don't affect the component's styles. |
| 49 | + |
| 50 | + |
| 51 | +* You can co-locate the CSS code of each component with the TypeScript and HTML code of the component, |
| 52 | + which leads to a neat and tidy project structure. |
| 53 | + |
| 54 | + |
| 55 | +* You can change or remove component CSS code without searching through the |
| 56 | + whole application to find where else the code is used. |
| 57 | + |
| 58 | +{@a special-selectors} |
| 59 | + |
| 60 | +## Special selectors |
| 61 | + |
| 62 | +Component styles have a few special *selectors* from the world of shadow DOM style scoping |
| 63 | +(described in the [CSS Scoping Module Level 1](https://www.w3.org/TR/css-scoping-1) page on the |
| 64 | +[W3C](https://www.w3.org) site). |
| 65 | +The following sections describe these selectors. |
| 66 | + |
| 67 | +### :host |
| 68 | + |
| 69 | +Use the `:host` pseudo-class selector to target styles in the element that *hosts* the component (as opposed to |
| 70 | +targeting elements *inside* the component's template). |
| 71 | + |
| 72 | + |
| 73 | +<code-example path="component-styles/src/app/hero-details.component.css" region="host" header="src/app/hero-details.component.css"></code-example> |
| 74 | + |
| 75 | +The `:host` selector is the only way to target the host element. You can't reach |
| 76 | +the host element from inside the component with other selectors because it's not part of the |
| 77 | +component's own template. The host element is in a parent component's template. |
| 78 | + |
| 79 | +Use the *function form* to apply host styles conditionally by |
| 80 | +including another selector inside parentheses after `:host`. |
| 81 | + |
| 82 | +The next example targets the host element again, but only when it also has the `active` CSS class. |
| 83 | + |
| 84 | +<code-example path="component-styles/src/app/hero-details.component.css" region="hostfunction" header="src/app/hero-details.component.css"></code-example> |
| 85 | + |
| 86 | +### :host-context |
| 87 | + |
| 88 | +Sometimes it's useful to apply styles based on some condition *outside* of a component's view. |
| 89 | +For example, a CSS theme class could be applied to the document `<body>` element, and |
| 90 | +you want to change how your component looks based on that. |
| 91 | + |
| 92 | +Use the `:host-context()` pseudo-class selector, which works just like the function |
| 93 | +form of `:host()`. The `:host-context()` selector looks for a CSS class in any ancestor of the component host element, |
| 94 | +up to the document root. The `:host-context()` selector is useful when combined with another selector. |
| 95 | + |
| 96 | +The following example applies a `background-color` style to all `<h2>` elements *inside* the component, only |
| 97 | +if some ancestor element has the CSS class `theme-light`. |
| 98 | + |
| 99 | +<code-example path="component-styles/src/app/hero-details.component.css" region="hostcontext" header="src/app/hero-details.component.css"></code-example> |
| 100 | + |
| 101 | +### (deprecated) `/deep/`, `>>>`, and `::ng-deep` |
| 102 | + |
| 103 | +Component styles normally apply only to the HTML in the component's own template. |
| 104 | + |
| 105 | +Applying the `::ng-deep` pseudo-class to any CSS rule completely disables view-encapsulation for |
| 106 | +that rule. Any style with `::ng-deep` applied becomes a global style. In order to scope the specified style |
| 107 | +to the current component and all its descendants, be sure to include the `:host` selector before |
| 108 | +`::ng-deep`. If the `::ng-deep` combinator is used without the `:host` pseudo-class selector, the style |
| 109 | +can bleed into other components. |
| 110 | + |
| 111 | +The following example targets all `<h3>` elements, from the host element down |
| 112 | +through this component to all of its child elements in the DOM. |
| 113 | + |
| 114 | +<code-example path="component-styles/src/app/hero-details.component.css" region="deep" header="src/app/hero-details.component.css"></code-example> |
| 115 | + |
| 116 | +The `/deep/` combinator also has the aliases `>>>`, and `::ng-deep`. |
| 117 | + |
| 118 | +<div class="alert is-important"> |
| 119 | + |
| 120 | +Use `/deep/`, `>>>` and `::ng-deep` only with *emulated* view encapsulation. |
| 121 | +Emulated is the default and most commonly used view encapsulation. For more information, see the |
| 122 | +[Controlling view encapsulation](guide/component-styles#view-encapsulation) section. |
| 123 | + |
| 124 | +</div> |
| 125 | + |
| 126 | +<div class="alert is-important"> |
| 127 | + |
| 128 | +The shadow-piercing descendant combinator is deprecated and [support is being removed from major browsers](https://www.chromestatus.com/features/6750456638341120) and tools. |
| 129 | +As such we plan to drop support in Angular (for all 3 of `/deep/`, `>>>` and `::ng-deep`). |
| 130 | +Until then `::ng-deep` should be preferred for a broader compatibility with the tools. |
| 131 | + |
| 132 | +</div> |
| 133 | + |
| 134 | +{@a loading-styles} |
| 135 | + |
| 136 | +## Loading component styles |
| 137 | + |
| 138 | +There are several ways to add styles to a component: |
| 139 | + |
| 140 | +* By setting `styles` or `styleUrls` metadata. |
| 141 | +* Inline in the template HTML. |
| 142 | +* With CSS imports. |
| 143 | + |
| 144 | +The scoping rules outlined earlier apply to each of these loading patterns. |
| 145 | + |
| 146 | +### Styles in component metadata |
| 147 | + |
| 148 | +You can add a `styles` array property to the `@Component` decorator. |
| 149 | + |
| 150 | +Each string in the array defines some CSS for this component. |
| 151 | + |
| 152 | +<code-example path="component-styles/src/app/hero-app.component.ts" header="src/app/hero-app.component.ts (CSS inline)"> |
| 153 | +</code-example> |
| 154 | + |
| 155 | +<div class="alert is-critical"> |
| 156 | + |
| 157 | +Reminder: these styles apply _only to this component_. |
| 158 | +They are _not inherited_ by any components nested within the template nor by any content projected into the component. |
| 159 | + |
| 160 | +</div> |
| 161 | + |
| 162 | +The Angular CLI command [`ng generate component`](cli/generate) defines an empty `styles` array when you create the component with the `--inline-style` flag. |
| 163 | + |
| 164 | +<code-example language="sh" class="code-shell"> |
| 165 | +ng generate component hero-app --inline-style |
| 166 | +</code-example> |
| 167 | + |
| 168 | +### Style files in component metadata |
| 169 | + |
| 170 | +You can load styles from external CSS files by adding a `styleUrls` property |
| 171 | +to a component's `@Component` decorator: |
| 172 | + |
| 173 | +<code-tabs> |
| 174 | + <code-pane header="src/app/hero-app.component.ts (CSS in file)" path="component-styles/src/app/hero-app.component.1.ts"></code-pane> |
| 175 | + <code-pane header="src/app/hero-app.component.css" path="component-styles/src/app/hero-app.component.css"></code-pane> |
| 176 | +</code-tabs> |
| 177 | + |
| 178 | +<div class="alert is-critical"> |
| 179 | + |
| 180 | +Reminder: the styles in the style file apply _only to this component_. |
| 181 | +They are _not inherited_ by any components nested within the template nor by any content projected into the component. |
| 182 | + |
| 183 | +</div> |
| 184 | + |
| 185 | +<div class="alert is-helpful"> |
| 186 | + |
| 187 | + You can specify more than one styles file or even a combination of `styles` and `styleUrls`. |
| 188 | + |
| 189 | +</div> |
| 190 | + |
| 191 | +When you use the Angular CLI command [`ng generate component`](cli/generate) without the `--inline-style` flag, it creates an empty styles file for you and references that file in the component's generated `styleUrls`. |
| 192 | + |
| 193 | +<code-example language="sh" class="code-shell"> |
| 194 | +ng generate component hero-app |
| 195 | +</code-example> |
| 196 | + |
| 197 | +### Template inline styles |
| 198 | + |
| 199 | +You can embed CSS styles directly into the HTML template by putting them |
| 200 | +inside `<style>` tags. |
| 201 | + |
| 202 | +<code-example path="component-styles/src/app/hero-controls.component.ts" region="inlinestyles" header="src/app/hero-controls.component.ts"> |
| 203 | +</code-example> |
| 204 | + |
| 205 | +### Template link tags |
| 206 | + |
| 207 | +You can also write `<link>` tags into the component's HTML template. |
| 208 | + |
| 209 | +<code-example path="component-styles/src/app/hero-team.component.ts" region="stylelink" header="src/app/hero-team.component.ts"> |
| 210 | +</code-example> |
| 211 | + |
| 212 | +<div class="alert is-critical"> |
| 213 | + |
| 214 | +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 [CLI wiki](https://github.com/angular/angular-cli/wiki/stories-asset-configuration). |
| 215 | +<!-- 2018-10-16: The link above is still the best source for this information. --> |
| 216 | + |
| 217 | +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. |
| 218 | + |
| 219 | +</div> |
| 220 | + |
| 221 | +### CSS @imports |
| 222 | + |
| 223 | +You can also import CSS files into the CSS files using the standard CSS `@import` rule. |
| 224 | +For details, see [`@import`](https://developer.mozilla.org/en/docs/Web/CSS/@import) |
| 225 | +on the [MDN](https://developer.mozilla.org) site. |
| 226 | + |
| 227 | +In this case, the URL is relative to the CSS file into which you're importing. |
| 228 | + |
| 229 | +<code-example path="component-styles/src/app/hero-details.component.css" region="import" header="src/app/hero-details.component.css (excerpt)"> |
| 230 | +</code-example> |
| 231 | + |
| 232 | +### External and global style files |
| 233 | + |
| 234 | +When building with the CLI, you must configure the `angular.json` to include _all external assets_, including external style files. |
| 235 | + |
| 236 | +Register **global** style files in the `styles` section which, by default, is pre-configured with the global `styles.css` file. |
| 237 | + |
| 238 | +See the [CLI wiki](https://github.com/angular/angular-cli/wiki/stories-global-styles) to learn more. |
| 239 | +<!-- 2018-10-16: The link above is still the best source for this information. --> |
| 240 | + |
| 241 | + |
| 242 | +### Non-CSS style files |
| 243 | + |
| 244 | +If you're building with the CLI, |
| 245 | +you can write style files in [sass](http://sass-lang.com/), [less](http://lesscss.org/), or [stylus](http://stylus-lang.com/) and specify those files in the `@Component.styleUrls` metadata with the appropriate extensions (`.scss`, `.less`, `.styl`) as in the following example: |
| 246 | + |
| 247 | +<code-example> |
| 248 | +@Component({ |
| 249 | + selector: 'app-root', |
| 250 | + templateUrl: './app.component.html', |
| 251 | + styleUrls: ['./app.component.scss'] |
| 252 | +}) |
| 253 | +... |
| 254 | +</code-example> |
| 255 | + |
| 256 | +The CLI build process runs the pertinent CSS preprocessor. |
| 257 | + |
| 258 | +When generating a component file with `ng generate component`, the CLI emits an empty CSS styles file (`.css`) by default. |
| 259 | +You can configure the CLI to default to your preferred CSS preprocessor |
| 260 | +as explained in the [CLI wiki](https://github.com/angular/angular-cli/wiki/stories-css-preprocessors |
| 261 | +"CSS Preprocessor integration"). |
| 262 | +<!-- 2018-10-16: The link above is still the best source for this information. --> |
| 263 | + |
| 264 | + |
| 265 | +<div class="alert is-important"> |
| 266 | + |
| 267 | +Style strings added to the `@Component.styles` array _must be written in CSS_ because the CLI cannot apply a preprocessor to inline styles. |
| 268 | + |
| 269 | +</div> |
| 270 | + |
| 271 | +{@a view-encapsulation} |
| 272 | + |
| 273 | +## View encapsulation |
| 274 | + |
| 275 | +As discussed earlier, component CSS styles are encapsulated into the component's view and don't |
| 276 | +affect the rest of the application. |
| 277 | + |
| 278 | +To control how this encapsulation happens on a *per |
| 279 | +component* basis, you can set the *view encapsulation mode* in the component metadata. |
| 280 | +Choose from the following modes: |
| 281 | + |
| 282 | +* `ShadowDom` view encapsulation uses the browser's native shadow DOM implementation (see |
| 283 | + [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM) |
| 284 | + on the [MDN](https://developer.mozilla.org) site) |
| 285 | + to attach a shadow DOM to the component's host element, and then puts the component |
| 286 | + view inside that shadow DOM. The component's styles are included within the shadow DOM. |
| 287 | + |
| 288 | +* `Native` view encapsulation uses a now deprecated version of the browser's native shadow DOM implementation - [learn about the changes](https://hayato.io/2016/shadowdomv1/). |
| 289 | + |
| 290 | +* `Emulated` view encapsulation (the default) emulates the behavior of shadow DOM by preprocessing |
| 291 | + (and renaming) the CSS code to effectively scope the CSS to the component's view. |
| 292 | + For details, see [Inspecting generated CSS](guide/component-styles#inspect-generated-css) below. |
| 293 | + |
| 294 | +* `None` means that Angular does no view encapsulation. |
| 295 | + Angular adds the CSS to the global styles. |
| 296 | + The scoping rules, isolations, and protections discussed earlier don't apply. |
| 297 | + This is essentially the same as pasting the component's styles into the HTML. |
| 298 | + |
| 299 | +To set the components encapsulation mode, use the `encapsulation` property in the component metadata: |
| 300 | + |
| 301 | +<code-example path="component-styles/src/app/quest-summary.component.ts" region="encapsulation.native" header="src/app/quest-summary.component.ts"></code-example> |
| 302 | + |
| 303 | +`ShadowDom` view encapsulation only works on browsers that have native support |
| 304 | +for shadow DOM (see [Shadow DOM v1](https://caniuse.com/#feat=shadowdomv1) on the |
| 305 | +[Can I use](http://caniuse.com) site). The support is still limited, |
| 306 | +which is why `Emulated` view encapsulation is the default mode and recommended |
| 307 | +in most cases. |
| 308 | + |
| 309 | +{@a inspect-generated-css} |
| 310 | + |
| 311 | +## Inspecting generated CSS |
| 312 | + |
| 313 | +When using emulated view encapsulation, Angular preprocesses |
| 314 | +all component styles so that they approximate the standard shadow CSS scoping rules. |
| 315 | + |
| 316 | +In the DOM of a running Angular application with emulated view |
| 317 | +encapsulation enabled, each DOM element has some extra attributes |
| 318 | +attached to it: |
| 319 | + |
| 320 | +<code-example format=""> |
| 321 | + <hero-details _nghost-pmm-5> |
| 322 | + <h2 _ngcontent-pmm-5>Mister Fantastic</h2> |
| 323 | + <hero-team _ngcontent-pmm-5 _nghost-pmm-6> |
| 324 | + <h3 _ngcontent-pmm-6>Team</h3> |
| 325 | + </hero-team> |
| 326 | + </hero-detail> |
| 327 | + |
| 328 | +</code-example> |
| 329 | + |
| 330 | +There are two kinds of generated attributes: |
| 331 | + |
| 332 | +* An element that would be a shadow DOM host in native encapsulation has a |
| 333 | + generated `_nghost` attribute. This is typically the case for component host elements. |
| 334 | +* An element within a component's view has a `_ngcontent` attribute |
| 335 | +that identifies to which host's emulated shadow DOM this element belongs. |
| 336 | + |
| 337 | +The exact values of these attributes aren't important. They are automatically |
| 338 | +generated and you never refer to them in application code. But they are targeted |
| 339 | +by the generated component styles, which are in the `<head>` section of the DOM: |
| 340 | + |
| 341 | +<code-example format=""> |
| 342 | + [_nghost-pmm-5] { |
| 343 | + display: block; |
| 344 | + border: 1px solid black; |
| 345 | + } |
| 346 | + |
| 347 | + h3[_ngcontent-pmm-6] { |
| 348 | + background-color: white; |
| 349 | + border: 1px solid #777; |
| 350 | + } |
| 351 | +</code-example> |
| 352 | + |
| 353 | +These styles are post-processed so that each selector is augmented |
| 354 | +with `_nghost` or `_ngcontent` attribute selectors. |
| 355 | +These extra selectors enable the scoping rules described in this page. |
0 commit comments