mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
docs(core): improve viewEncapsulation documentation (#44151)
Slighlty improve the `viewEncapsulation` documentation (both in code comments and content files) to make it more clear and understandable. See https://github.com/angular/angular/pull/44099#discussion_r745890903 PR Close #44151
This commit is contained in:
parent
2bf131a8a0
commit
6ae38584b0
6 changed files with 72 additions and 85 deletions
|
|
@ -10,9 +10,3 @@ import { Component } from '@angular/core';
|
|||
})
|
||||
export class QuestSummaryComponent { }
|
||||
// #enddocregion
|
||||
/*
|
||||
// #docregion encapsulation.shadow
|
||||
// warning: not all browsers support shadow DOM encapsulation at this time
|
||||
encapsulation: ViewEncapsulation.ShadowDom
|
||||
// #enddocregion encapsulation.shadow
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,46 +1,37 @@
|
|||
# View encapsulation
|
||||
|
||||
In Angular, component CSS styles are encapsulated into the component's view and don't
|
||||
affect the rest of the application.
|
||||
In Angular, a component's styles can be encapsulated within the component's host element so that they don't affect the rest of the application.
|
||||
|
||||
The `Component`'s decorator provides the [`encapsulation`](api/core/Component#encapsulation) option which can be used to control how the encapsulation is applied on a _per component_ basis.
|
||||
|
||||
To control how this encapsulation happens on a _per
|
||||
component_ basis, set the _view encapsulation mode_ in the component metadata.
|
||||
Choose from the following modes:
|
||||
|
||||
- `ShadowDom` view encapsulation uses the browser's built-in shadow DOM implementation (see
|
||||
[Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM))
|
||||
to attach a shadow DOM to the component's host element, and then puts the component
|
||||
view inside that shadow DOM. The component's styles are included within the shadow DOM.
|
||||
- `ViewEncapsulation.ShadowDom`, Angular uses the browser's built-in [Shadow DOM API](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM)) to enclose the component's view inside a ShadowRoot (used as the component's host element) and apply the provided styles in an isolated manner.
|
||||
|
||||
- `Emulated` view encapsulation (the default) emulates the behavior of shadow DOM by preprocessing
|
||||
(and renaming) the CSS code to effectively scope the CSS to the component's view.
|
||||
For details, see [Inspecting generated CSS](guide/view-encapsulation#inspect-generated-css).
|
||||
- `ViewEncapsulation.Emulated`, Angular modifies the component's CSS selectors so that they are only applied to the component's view and do not affect other elements in the application (_emulating_ Shadow DOM behavior). For more details, see [Inspecting generated CSS](guide/view-encapsulation#inspect-generated-css).
|
||||
|
||||
- `None` means that Angular does no view encapsulation.
|
||||
Angular adds the CSS to the global styles.
|
||||
The scoping rules, isolations, and protections discussed earlier don't apply.
|
||||
This mode is essentially the same as pasting the component's styles into the HTML.
|
||||
- `ViewEncapsulation.None`, Angular does not apply any sort of view encapsulation meaning that any styles specified
|
||||
for the component are actually globally applied and can affect any HTML element present within the application.
|
||||
This mode is essentially the same as including the styles into the HTML itself.
|
||||
|
||||
To set the component's encapsulation mode, use the `encapsulation` property in the component metadata:
|
||||
<div class="alert is-important">
|
||||
|
||||
<code-example path="component-styles/src/app/quest-summary.component.ts" region="encapsulation.shadow" header="src/app/quest-summary.component.ts"></code-example>
|
||||
`ViewEncapsulation.ShadowDom` only works on browsers that have built-in support
|
||||
for the shadow DOM (see [Can I use - Shadow DOM v1](https://caniuse.com/shadowdomv1)).
|
||||
Not all browsers support it, which is why the `ViewEncapsulation.Emulated` is the recommended and default mode.
|
||||
|
||||
</div>
|
||||
|
||||
`ShadowDom` view encapsulation only works on browsers that have built-in support
|
||||
for shadow DOM (see [Can I use - Shadow DOM v1](https://caniuse.com/shadowdomv1)).
|
||||
The support is still limited, which is why `Emulated` view encapsulation is the default mode and recommended in most cases.
|
||||
|
||||
{@a inspect-generated-css}
|
||||
|
||||
## Inspecting generated CSS
|
||||
|
||||
When using emulated view encapsulation, Angular preprocesses
|
||||
all component styles so that they approximate the standard shadow CSS scoping rules.
|
||||
When using the emulated view encapsulation, Angular pre-processes all the component's styles so that they are only applied to the component's view.
|
||||
|
||||
In the DOM of a running Angular application with emulated view
|
||||
encapsulation enabled, each DOM element has some extra attributes
|
||||
attached to it:
|
||||
In the DOM of a running Angular application, elements belonging to components using emulated view encapsulation have some extra attributes attached to them:
|
||||
|
||||
<code-example format="">
|
||||
<code-example format="html" language="html">
|
||||
<hero-details _nghost-pmm-5>
|
||||
<h2 _ngcontent-pmm-5>Mister Fantastic</h2>
|
||||
<hero-team _ngcontent-pmm-5 _nghost-pmm-6>
|
||||
|
|
@ -49,18 +40,16 @@ attached to it:
|
|||
</hero-detail>
|
||||
</code-example>
|
||||
|
||||
There are two kinds of generated attributes:
|
||||
There are two kinds of such attributes:
|
||||
|
||||
- An element that would be a shadow DOM host in native encapsulation has a
|
||||
generated `_nghost` attribute. This is typically the case for component host elements.
|
||||
- An element within a component's view has a `_ngcontent` attribute
|
||||
that identifies to which host's emulated shadow DOM this element belongs.
|
||||
- `_nghost` attributes are added to elements that enclose a component's view and that would be ShadowRoots in a native Shadow DOM encapsulation. This is typically the case for components' host elements.
|
||||
- `_ngcontent` attributes are added to child element within a component's view, those are used to match the elements with their respective emulated ShadowRoots (host elements with a matching `_nghost` attribute).
|
||||
|
||||
The exact values of these attributes aren't important. They are automatically
|
||||
generated and you should never refer to them in application code. But they are targeted
|
||||
by the generated component styles, which are in the `<head>` section of the DOM:
|
||||
The exact values of these attributes are a private implementation detail of Angular. They are automatically generated and you should never refer to them in application code.
|
||||
|
||||
<code-example format="">
|
||||
They are targeted by the generated component styles, which are injected in the `<head>` section of the DOM:
|
||||
|
||||
<code-example format="css" language="css">
|
||||
[_nghost-pmm-5] {
|
||||
display: block;
|
||||
border: 1px solid black;
|
||||
|
|
@ -72,25 +61,29 @@ h3[_ngcontent-pmm-6] {
|
|||
}
|
||||
</code-example>
|
||||
|
||||
These styles are post-processed so that each selector is augmented
|
||||
with `_nghost` or `_ngcontent` attribute selectors.
|
||||
These extra selectors enable the scoping rules described in this page.
|
||||
These styles are post-processed so that each CSS selector is augmented with the appropriate `_nghost` or `_ngcontent` attribute. These modified selectors make sure the styles to be applied to components' views in an isolated and targeted fashion.
|
||||
|
||||
## Mixing encapsulation modes
|
||||
|
||||
Avoid mixing components that use different view encapsulation. Where it is necessary, you should be aware of how the component styles will interact.
|
||||
As previously mentioned you specify the encapsulation mode in the Component's decorator on a _per component_ basis, this means that within your application you can have different components using different encapsulation strategies.
|
||||
|
||||
- The styles of components with `ViewEncapsulation.Emulated` are added to the `<head>` of the document, making them available throughout the application, but are "scoped" so they only affect elements within the component's template.
|
||||
Although possible, this is not recommended. If it is really needed you should be aware of how the styles of components using different encapsulation modes will interact with each other:
|
||||
|
||||
- The styles of components with `ViewEncapsulation.None` are added to the `<head>` of the document, making them available throughout the application, and are not "scoped" so they can affect any element in the application.
|
||||
- The styles of components with `ViewEncapsulation.Emulated` are added to the `<head>` of the document, making them available throughout the application, but their selectors only affect elements within their respective components' templates.
|
||||
|
||||
- The styles of components with `ViewEncapsulation.ShadowDom` are only added to the shadow DOM host, ensuring that they only affect elements within the component's template.
|
||||
- The styles of components with `ViewEncapsulation.None` are added to the `<head>` of the document, making them available throughout the application, so are completely global and affect any matching elements within the document.
|
||||
|
||||
**All the styles for `ViewEncapsulation.Emulated` and `ViewEncapsulation.None` components are also added to the shadow DOM host of each `ViewEncapsulation.ShadowDom` component.**
|
||||
- The styles of components with `ViewEncapsulation.ShadowDom` are only added to the shadow DOM host, ensuring that they only affect elements within their respective components' views.
|
||||
|
||||
The result is that styling for components with `ViewEncapsulation.None` will affect matching elements within the shadow DOM.
|
||||
<div class="alert is-helpful">
|
||||
|
||||
This approach may seem counter-intuitive at first, but without it a component with `ViewEncapsulation.None` could not be used within a component with `ViewEncapsulation.ShadowDom`, since its styles would not be available.
|
||||
Styles of `ViewEncapsulation.Emulated` and `ViewEncapsulation.None` components are also added to the shadow DOM host of each `ViewEncapsulation.ShadowDom` component.
|
||||
|
||||
This means that styles for components with `ViewEncapsulation.None` will affect matching elements within shadow DOMs.
|
||||
|
||||
This approach may seem counter-intuitive at first, but without it a component with `ViewEncapsulation.None` would be rendered differently within a component using `ViewEncapsulation.ShadowDom`, since its styles would not be available.
|
||||
|
||||
</div>
|
||||
|
||||
### Examples
|
||||
|
||||
|
|
@ -106,7 +99,7 @@ The first example shows a component that has `ViewEncapsulation.None`. This comp
|
|||
|
||||
Angular adds the styles for this component as global styles to the `<head>` of the document.
|
||||
|
||||
**Angular also adds the styles to all shadow DOM hosts.** Therefore, the styles are available throughout the application.
|
||||
As already mentioned Angular also adds the styles to all shadow DOM hosts. Therefore, the styles are available throughout the whole application.
|
||||
|
||||
<img src="generated/images/guide/view-encapsulation/no-encapsulation.png" alt="component with no encapsulation">
|
||||
|
||||
|
|
@ -116,14 +109,12 @@ The second example shows a component that has `ViewEncapsulation.Emulated`. This
|
|||
|
||||
<code-example path="view-encapsulation/src/app/emulated-encapsulation.component.ts" header="src/app/emulated-encapsulation.component.ts"></code-example>>
|
||||
|
||||
Similar to `ViewEncapsulation.None`, Angular adds the styles for this component to the `<head>` of the document, and to all the shadow DOM hosts.
|
||||
But in this case, the styles are "scoped" by the attributes described in ["Inspecting generated CSS"](#inspecting-generated-css).
|
||||
Similar to `ViewEncapsulation.None`, Angular adds the styles for this component to the `<head>` of the document, but with "scoped" styles.
|
||||
|
||||
Therefore, only the elements directly within this component's template will match its styles.
|
||||
Since the "scoped" styles from the `EmulatedEncapsulationComponent` are very specific, they override the global styles from the `NoEncapsulationComponent`.
|
||||
|
||||
In this example, the `EmulatedEncapsulationComponent` contains a `NoEncapsulationComponent`.
|
||||
The `NoEncapsulationComponent` is styled as expected because the scoped styles do not match elements in its template.
|
||||
In this example, the `EmulatedEncapsulationComponent` contains a `NoEncapsulationComponent`, but `NoEncapsulationComponent` is still styled as expected since the `EmulatedEncapsulationComponent`'s "scoped" styles do not match elements in its template.
|
||||
|
||||
<img src="generated/images/guide/view-encapsulation/emulated-encapsulation.png" alt="component with no encapsulation">
|
||||
|
||||
|
|
@ -144,8 +135,8 @@ The styles added by the `ShadowDomEncapsulationComponent` component are availabl
|
|||
The `EmulatedEncapsulationComponent` has specific "scoped" styles, so the styling of this component's template is unaffected.
|
||||
|
||||
But since styles from `ShadowDomEncapsulationComponent` are added to the shadow host after the global styles, the `h2` style overrides the style from the `NoEncapsulationComponent`.
|
||||
The result is that the `<h2>` element in the `NoEncapsulationComponent` is colored blue rather than red, which may not be what the component author intended.
|
||||
The result is that the `<h2>` element in the `NoEncapsulationComponent` is colored blue rather than red, which may not be what the component's author intended.
|
||||
|
||||
<img src="generated/images/guide/view-encapsulation/shadow-dom-encapsulation.png" alt="component with no encapsulation">
|
||||
|
||||
@reviewed 2021-09-17
|
||||
@reviewed 2021-11-10
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ export interface R3DeclareComponentMetadata extends R3DeclareDirectiveMetadata {
|
|||
changeDetection?: ChangeDetectionStrategy;
|
||||
|
||||
/**
|
||||
* An encapsulation policy for the template and CSS styles.
|
||||
* An encapsulation policy for the component's styling.
|
||||
* Defaults to `ViewEncapsulation.Emulated`.
|
||||
*/
|
||||
encapsulation?: ViewEncapsulation;
|
||||
|
|
|
|||
|
|
@ -206,11 +206,12 @@ export interface R3ComponentMetadata extends R3DirectiveMetadata {
|
|||
styles: string[];
|
||||
|
||||
/**
|
||||
* An encapsulation policy for the template and CSS styles. One of:
|
||||
* - `ViewEncapsulation.Emulated`: Use shimmed CSS that emulates the native behavior.
|
||||
* - `ViewEncapsulation.None`: Use global CSS without any encapsulation.
|
||||
* - `ViewEncapsulation.ShadowDom`: Use the latest ShadowDOM API to natively encapsulate styles
|
||||
* into a shadow root.
|
||||
* An encapsulation policy for the component's styling.
|
||||
* Possible values:
|
||||
* - `ViewEncapsulation.Emulated`: Apply modified component styles in order to emulate
|
||||
* a native Shadow DOM CSS encapsulation behavior.
|
||||
* - `ViewEncapsulation.None`: Apply component styles globally without any sort of encapsulation.
|
||||
* - `ViewEncapsulation.ShadowDom`: Use the browser's native Shadow DOM API to encapsulate styles.
|
||||
*/
|
||||
encapsulation: ViewEncapsulation;
|
||||
|
||||
|
|
|
|||
|
|
@ -516,18 +516,19 @@ export interface Component extends Directive {
|
|||
animations?: any[];
|
||||
|
||||
/**
|
||||
* An encapsulation policy for the template and CSS styles. One of:
|
||||
* - `ViewEncapsulation.Emulated`: Use shimmed CSS that
|
||||
* emulates the native behavior.
|
||||
* - `ViewEncapsulation.None`: Use global CSS without any
|
||||
* encapsulation.
|
||||
* - `ViewEncapsulation.ShadowDom`: Use Shadow DOM v1 to encapsulate styles.
|
||||
* An encapsulation policy for the component's styling.
|
||||
* Possible values:
|
||||
* - `ViewEncapsulation.Emulated`: Apply modified component styles in order to emulate
|
||||
* a native Shadow DOM CSS encapsulation behavior.
|
||||
* - `ViewEncapsulation.None`: Apply component styles globally without any sort of encapsulation.
|
||||
* - `ViewEncapsulation.ShadowDom`: Use the browser's native Shadow DOM API to encapsulate styles.
|
||||
*
|
||||
* If not supplied, the value is taken from `CompilerOptions`. The default compiler option is
|
||||
* `ViewEncapsulation.Emulated`.
|
||||
* If not supplied, the value is taken from the `CompilerOptions`
|
||||
* which defaults to `ViewEncapsulation.Emulated`.
|
||||
*
|
||||
* If the policy is set to `ViewEncapsulation.Emulated` and the component has no `styles`
|
||||
* or `styleUrls` specified, the policy is automatically switched to `ViewEncapsulation.None`.
|
||||
* If the policy is `ViewEncapsulation.Emulated` and the component has no
|
||||
* {@link Component#styles styles} nor {@link Component#styleUrls styleUrls},
|
||||
* the policy is automatically switched to `ViewEncapsulation.None`.
|
||||
*/
|
||||
encapsulation?: ViewEncapsulation;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Defines template and style encapsulation options available for Component's {@link Component}.
|
||||
* Defines the CSS styles encapsulation policies for the {@link Component} decorator's
|
||||
* `encapsulation` option.
|
||||
*
|
||||
* See {@link Component#encapsulation encapsulation}.
|
||||
*
|
||||
|
|
@ -23,10 +24,9 @@ export enum ViewEncapsulation {
|
|||
// https://github.com/angular/angular/issues/44119 for additional information.
|
||||
|
||||
/**
|
||||
* Emulate `Native` scoping of styles by adding an attribute containing surrogate id to the Host
|
||||
* Element and pre-processing the style rules provided via {@link Component#styles styles} or
|
||||
* {@link Component#styleUrls styleUrls}, and adding the new Host Element attribute to all
|
||||
* selectors.
|
||||
* Emulates a native Shadow DOM encapsulation behavior by adding a specific attribute to the
|
||||
* component's host element and applying the same attribute to all the CSS selectors provided
|
||||
* via {@link Component#styles styles} or {@link Component#styleUrls styleUrls}.
|
||||
*
|
||||
* This is the default option.
|
||||
*/
|
||||
|
|
@ -35,16 +35,16 @@ export enum ViewEncapsulation {
|
|||
// Historically the 1 value was for `Native` encapsulation which has been removed as of v11.
|
||||
|
||||
/**
|
||||
* Don't provide any template or style encapsulation.
|
||||
* Doesn't provide any sort of CSS style encapsulation, meaning that all the styles provided
|
||||
* via {@link Component#styles styles} or {@link Component#styleUrls styleUrls} are applicable
|
||||
* to any HTML element of the application regardless of their host Component.
|
||||
*/
|
||||
None = 2,
|
||||
|
||||
/**
|
||||
* Use Shadow DOM to encapsulate styles.
|
||||
*
|
||||
* For the DOM this means using modern [Shadow
|
||||
* DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM) and
|
||||
* creating a ShadowRoot for Component's Host Element.
|
||||
* Uses the browser's native Shadow DOM API to encapsulate CSS styles, meaning that it creates
|
||||
* a ShadowRoot for the component's host element which is then used to encapsulate
|
||||
* all the Component's styling.
|
||||
*/
|
||||
ShadowDom = 3
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue