question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Styles from external components are included outside the scope of a shadow DOM component

See original GitHub issue

🐞 bug report

Affected Package

The issue is caused by package @angular/platform-browser

Is this a regression?

No

Description

When deploying an Angular component with encapsulation: ViewEncapsulation.ShadowDom, everything regarding the component should be kept inside the #shadow-root. This includes all stylings.

Actual behavior

  1. Styles added by styleUrls or styles in the @Component decorator are added to the #shadow-root ✔️
  2. Styles coming from external components like @angular/material are added to the #shadow-root ✔️
  3. Styles coming from external components are also added to document’s <head> outside of the #shadow-root

Expected behavior

Only 1. and 2. should happen.

Root cause analysis

As far as I can see, this is caused by the ShadowDomRenderer using the DomSharedStylesHost which adds _doc.head to its list of known _hostNodes in the constructor: https://github.com/angular/angular/blob/d43187f7ef7e841d84ecf594e8e515a9d534daaa/packages/platform-browser/src/dom/shared_styles_host.ts#L39

🔬 Minimal Reproduction

https://stackblitz.com/edit/angular-material-shadowdom-styles

In the <head> section there are <style> tags of Material components, which should only be inside the shadow DOM.

🌍 Your Environment

Angular Version:


Angular CLI: 8.3.23
Node: 12.7.0
OS: win32 x64
Angular: 8.2.14
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.803.23
@angular-devkit/build-angular     0.803.23
@angular-devkit/build-optimizer   0.803.23
@angular-devkit/build-webpack     0.803.23
@angular-devkit/core              8.3.23
@angular-devkit/schematics        8.3.23
@angular/cdk                      8.2.3
@angular/cli                      8.3.23
@angular/material                 8.2.3
@ngtools/webpack                  8.3.23
@schematics/angular               8.3.23
@schematics/update                0.803.23
rxjs                              6.4.0
typescript                        3.5.3
webpack                           4.39.2

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:4
  • Comments:5

github_iconTop GitHub Comments

2reactions
courtney-regiscommented, Nov 20, 2020

@Megadesty

We have encountered the same issue. One way we’ve worked around it is that we have a project dedicated to creating web components. In the bootstrapped module where we declare our custom elements, we do the following in the constructor of the NgModule:

import { Injector } from "@angular/core";
import { ɵDomSharedStylesHost } from "@angular/platform-browser";

constructor(private injector: Injector) {
    this.injector.get(ɵDomSharedStylesHost).removeHost(document.head);
}

2reactions
Megadestycommented, Apr 6, 2020

@alexeykostevich Your extended example is excellent and showcases the (faulty) behavior with components ViewEncapsulation.Emulated inside a #shadow-root as well, thanks!

I think if you are happy with the surrogate ids, that’s fine. But as you can see in my and your example, the common Material styles (like .mat-card {...}) are also included in both the document and #shadow-root. Now think about having mulitple Web Components on one page, all are self-contained Angular apps using Material. What you get in the end is that each component injects its own Material style in the document and since they are always named the same, they are overwriting each other. This could lead to trouble if one Web Component uses an older Angular or Material version or another Material theme. And even if all Web Components are using the same Material version and the same theme, in my opinion this is not good at all.

In our case we already have multiple Web Components using Angular with Material on a page. The document’s <head> looks like this:

image

If the Angular team fixes this issue, I guess it won’t have an impact on your project. Except you are using global styles from a Web Component outside the component, but that sounds like a bad practice anyway.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Using shadow DOM - Web Components | MDN
Shadow DOM allows hidden DOM trees to be attached to elements in the regular DOM tree — this shadow DOM tree starts with...
Read more >
Scoping CSS using Shadow DOM - Bits and Pieces
Shadow DOM provides out-of-the-box style isolation and DOM encapsulation, perfect for self-contained, reusable components for your UIs. Browser ...
Read more >
Style an element's shadow DOM - Polymer Project
Shadow DOM permits encapsulation of styling rules for custom elements. You can freely define styling information for your elements, such as fonts, text...
Read more >
Encapsulating Style and Structure with Shadow DOM
The shadow DOM specification includes a means for allowing content from outside the shadow root to be rendered inside of our custom element....
Read more >
Styles - Lit.dev
If Lit did not use Shadow DOM, you would have to be extremely careful not to accidentally style elements outside of your component,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found