When and why should we use View Encapsulation in angular
Codecraft.TV has an amazing article on ViewEncapsulation
that you can refer to get a better understanding.
To just summarize it:
ViewEncapsulation.Emulated
: Angular changes our generic css class selector to one that target just a single component type by using automatically generated attributes.Any styles we define on a component don’t leak out to the rest of the application but with
ViewEncapsulation.Emulated
our component still inherits global styles.
ViewEncapsulation.Native
: If we want Angular to use the shadow DOM we can set the encapsulation parameter to useViewEncapsulation.Native
With
ViewEncapsulation.Native
styles we set on a component do not leak outside of the components scope.This is great if we are defining a 3rd party component which we want people to use in isolation. We can describe the look for our component using css styles without any fear that our styles are going to leak out and affect the rest of the application.
However with
ViewEncapsulation.Native
our component is also isolated from the global styles we’ve defined for our application. So we don’t inherit the global styles and have to define all the required styles on our component decorator.Finally
ViewEncapsulation.Native
requires a feature called the shadow DOM which is not supported by all browsers.
ViewEncapsulation.None
: If we don’t want to have any encapsulation at all, we can useViewEncapsulation.None
.If we don't encapsulate anything, the style we defined in the component will leak out and started affecting the other components.
Some other resources that you might want to have a look into:
- VIEW ENCAPSULATION IN ANGULAR - By Thoughtram
- View Encapsulation by Rangle.IO
- Scoping Your Styles in Angular With ViewEncapsulationView
- Diff between ViewEncapsulation.Native, ViewEncapsulation.None and ViewEncapsulation.Emulated
How default view encapsulation works in Angular
There are three types of encapsulation in angular
- ViewEncapsulation.Emulated and this is set by default
- ViewEncapsulation.None
- ViewEncapsulation.Native
Emulated mode
Assume that you have two different components comp-first and comp-second , For example you define in both of them
<p> Some paragraph </p>
So if you apply some styling for paragraph in comp-first.css
p {
color: blue;
}
and then inspect p element on comp-first.html and look for its styling will find something like this
p[_ngcontent-ejo-1] {
color: blue;
}
"_ngcontent-ejo-1" is just a simple key for differentiate such an element from others components elements
None mode
If you apply this mode to such a component for instance comp-first and then you go and inspect any element it will not provide any attribute like "_ngcontent-ejo-1" to any element , So applying any styling or class it will be provided globally .
Native mode
This should give the same result as if you are using emulated mode but it comes with Shadow DOM technology in browsers which support it
Angular view encapsulation with external libraries
You can define this in your css. However, be carefull as ::ng-deep is quite a powerfull combinator and can cause problems if not used correctly.
Also from the Angular website:
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.
CSS:
:host { color: red; }
:host ::ng-deep parent {
color:blue;
}
:host ::ng-deep child{
color:orange;
}
:host ::ng-deep child.class1 {
color:yellow;
}
:host ::ng-deep child.class2{
color:pink;
}
HTML:
Angular2 //red
<parent> //blue
<child></child> //orange
<child class="class1"></child> //yellow
<child class="class2"></child> //pink
</parent>
Diff between ViewEncapsulation.Native, ViewEncapsulation.None and ViewEncapsulation.Emulated
update
If you want styles that are added to Parent
applied to Child
you need to set ViewEncapsulation.None
in the Child
component so it doesn't prevent styles to bleed in.
Emulated
and Native
are just two different ways to prevent styles to bleed in to and out from components. None
is the only one that allows styles to cross component boundaries.
original
ViewEncapsulation.None is simple no encapsulation
ViewEncapsulation.Emulated (currently the default in Angular2)
adds attributes to component tags and child elements and manipulates the CSS (adding the attributes to the selectors) added to the page so the styles don't bleed into each other - to keep styles scoped to the components where they are added even though the styles are all added collected in the head of the page when components are loaded.ViewEncapsulation.Native creates custom elements with shadow DOM where the browsers native implementation ensures the style scoping.
If the browser doesn't support shadow DOM natively, the web-components polyfills are required to shim the behavior. This is similar toViewEncapsulation.Emulated
but the polyfills are more expensive because they polyfill lots of browser APIs even when most of them are never used. AngularsEmulated
emulation just adds the cost for what it uses and is therefore much more efficient for Angular applications.
View Encapsulation Emulated, is it possible to escape emulated encapsulation within a stylesheet?
This is where the (deprecated) ::ng-deep
comes in play:
In your templates stylesheet:
:host ::ng-deep .ui-resizable-handle {
background-color: pink;
}
This will target any child element with the class ui-resizable-handle
from your component, regardless if it's declared in the template, a child component or dynamically added with a third party library, because this will compile to something like:
[_nghost-fav-c294] .ui-resizable-handle {
background-color: pink;
}
ViewEncapsulation ShadowDom vs Emulated
Answer: ViewEncapsulation.Emulated will add the css style in the head section of your website(and reference your component's unique id(_ngcontent) to apply it).
ViewEncapsulation.ShadowDom will add the css style inside the generated DOM of your component.
You could decorate your component with these two encapsulation and see the change in the style declaration in your website.
Note: ShadowDom is not supported by some of the legacy browsers.
Now performance-wise I think that ShadowDom will be better as the style are declared inside your component's div.
While Emulated will be better if you want to target the legacy browser as well.
ViewEncapsulation.Emulated styles are copied into #shadow-root by a ViewEncapsulation.(Native|ShadowDom) component
It's a known bug, the workaround at the moment is to basically not mix encapsulation modes.
But the scenario i assume you are encountering might be that you are mixing third parties having different types of encapsulation modes? If so you either have to take in consideration of your css structure or just simply rethink what third-party lib you are mixing.
Update
In consideration to comment make all components to run native encapsulation by telling compiler to do so with compilerOptions in order to not conflict with native web components.
Do so by adding in your tsconfig.json file(it's tsconfig.app.json in ng version 6+):
"angularCompilerOptions": {
"defaultEncapsulation": 1
}
Is it possible to style using :host with Encapsulation.None in Angular?
The component selector can be used as the CSS selector to style the host element when the encapsulation is set to ViewEncapsulation.None
:
/* With ViewEncapsulation.Emulated, use :host selector */
:host {
color: red;
}
/* With ViewEncapsulation.None, use component selector */
app-child-encapsulation-none {
color: green;
}
See this stackblitz for a demo.
Related Topics
CSS Table Border Spacing Inside Only
Fontello Glyph Font Odd Behaviour on Firefox, Shows Unicode Codes Instead of Icons
What's The Point of Gutters in CSS Grid Frameworks
Horizontal Line in Background Using CSS3
Styling: :-Webkit-Scrollbar-Track Not Working
Position: Relative Appearing Over Position:Absolute
Bootstrap 5 Form-Group, Form-Row, Form-Inline Not Working
Overriding Google Recaptcha CSS to Make It Responsive
Why Is Overflow Interacting with Z-Index
Overriding Styles in Semantic UI React
Div with Margin-Left and Width:100% Overflowing on The Right Side
How to Use The .Clearfix Class
How to Make a Text Go onto The Next Line If It Overflows