How Angular scopes styles to components - lordoftheflies/angular-essential-training GitHub Wiki
One of the major benefits of shadow Dom is the ability to scope CSS to a block of HTML meaning that the selectors will only apply to elements in that block. And the rules will not affect other elements in the document outside of that block. One of the drawbacks of shadow Dom is that it is not implemented in all browser vendors. The Angular framework fills that gap with its emulated view encapsulation mode, which is the default mode used when you don't specify a view in encapsulation configuration. In emulated mode, Angular is doing things with the CSS to encapsulate it to the component and its view contents. During the build, Angular run some pre-processing logic that will shim both the final CSS output and the template markup output to include some additional attributes that mimic the standard shadow CSS scoping rules. Let's take a look at how Angular handles the CSS we write for components after it does its build and it gets delivered to the browser when emulated mode is used. We will use the app component here to investigate the markup and CSS written in the project code and compare that to the final output. In the app.component.ts file, we have the styleUrls property being used to include a CSS file for this component. If we take a look at that app.component.css file, we can see that there are several selectors with rules defined. There is a :host one, some element selectors and some CSS class selectors. And these elements and classes are being used in the component template markup. Now we'll go over how to use these in an upcoming video but for now we'll just get a picture of what's in here so we can compare that to the final output. Over in the browser, we can use the dev tools to inspect the final markup with the elements tab. If we expand the head tag and the second style tag here, we can see that Angular has injected the CSS for the app component into this tag. And we can see that it is a bit different from how it is written in the component CSS file. Angular, during runtime will take the final component CSS and inject it into a style tag in the head tag. It does this for each component that is part of the currently rendered view when the view encapsulation mode is emulated. The other thing Angular will do is shim the CSS adding some specific attribute selectors onto each selector block denoted in CSS by the square brackets. Most of these have a string value of _ngcontent-something. This is a unique key that Angular generates for each component type to do the shimming. So in this case Angular has given the app component a unique attribute named _ngcontent-ojr-c0. There's also one named _nghost-ojr-c0, that one is used on the host element tag for the component and we will cover that in more detail in an upcoming video. If we scroll down and take a look at the mw-app element in the document body which is the selector used by the app component, we can see both the _nghost and _ngcontent on the mw-app element and its children elements. Angular is applying these attributes to the template markup for the component. By doing this, Angular is providing a unique scoping combination that maps the component CSS to the component template markup. If we expand the nav element, we can see the anchor tags in here have the same _ngcontent attribute applied to them. That is because those anchor tags are in the app component template markup. Every element in that component template markup will get this unique attribute applied to it. Now one important thing to note here is that Angular is generating this attribute string and it is not intended to be used when you write CSS for your components. This is considered compiled output. All you need to worry about is writing CSS the same way you'd write it for any standard web application, Angular will handle the rest for you. Let's expand the section element in here and take a look at another component. If we expand the mw-media-item-list element, we can see that this one has the _nghost and _ngcontent, but they have a suffix of -c1. That is Angular applying a unique key to the different component. So in emulated mode, the default view encapsulation mode for components, Angular will handle shimming the component CSS and template markup to ensure that the CSS written will be scoped to that component. This allows you to not have to worry about crafting any type of selector, syntax pattern on a global level to avoid collision and bleed and you can focus on writing the CSS to meet the needs of each individual component.