angular / components

Component infrastructure and Material Design components for Angular
https://material.angular.io
MIT License
24.27k stars 6.71k forks source link

docs: clarify support for ViewEncapsulation.ShadowDom #13837

Open Splaktar opened 5 years ago

Splaktar commented 5 years ago

Proposal

What is the expected behavior?

If ViewEncapsulation.ShadowDom is not supported, this should be called out in the docs to save developers time and frustration.

What is the current behavior?

ViewEncapsulation.ShadowDom is not supported and is not documented.

What are the steps to reproduce?

  1. Open https://stackblitz.com/edit/angular-i5jw3k?file=app/table-selection-example.ts
  2. Notice how the checkboxes aren't themed
  3. Open https://stackblitz.com/edit/angular-sbrzfb?file=app/input-overview-example.ts
  4. Notice how the inputs are not themed or styled properly

What is the use-case or motivation for changing an existing behavior?

To save developers time and frustration.

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Angular: 7.0.0 Angular Material: 7.0.2 TypeScript: ~3.1.1 Browsers: Tested on Chrome, Firefox, and Safari latest stable versions

Is there anything else we should know?

Nope

zlepper commented 5 years ago

Is there any plans to support ShadowDom at some point?

jelbourn commented 5 years ago

We have to define that "support" means, as well. We'll probably never change the components to use Shadow DOM, but when we switch to CSS variables the theming system won't prevent other people from using it.

xerofun commented 5 years ago

@jelbourn where is this on the road map (days, weeks, months)? We're starting to plow headlong into a webcomponent architecture but are heavily invested (and wish to remain so) with our material components.

Are you aware of a way to work around this. Since we're just starting off with componentizing some of our resources, it wouldn't be much effort to make the components happy with angular.

jelbourn commented 5 years ago

Switching the theming system to use CSS variables is probably going to be early 2020, but for other things (like overlays) we don't have concrete plans yet.

Splaktar commented 5 years ago

Note that when working with Angular Elements, ViewEncapsulation.None and using Sass (SCSS) to make sure that your styles are scoped to components is recommended at this time.

PapaNappa commented 4 years ago

We are now approaching mid 2020. What is the status and roadmap of this?

Being able to use material in components with ShadowDom opens a lot of opportunities and cleaner components/code/CSS.

Devstone11 commented 3 years ago

Hi folks, just bumping this issue again. Is there a recommended way to use ShadowDom without losing all the styling on Material components?

jelbourn commented 3 years ago

Angular is dropping IE11 support in v13, which opens the door to us switching to CSS variables, which would make it possible to support Shadow DOM.

Sometime in the next year we do plan on revamping our theming system. This would involve switching to CSS variables and aligning more closely with the current Material Design spec, and would probably coincide with moving the MDC-based components to stable. However, we don't yet have the detailed design of what that would look like.

alex737876 commented 1 year ago

As MDC based components are beeing used for Material since Angular 15, i want to just bump this issue. Does this have any meaning to Material/ShadowDom?

MirkoAdolph commented 7 months ago

We are now approaching mid 2020. What is the status and roadmap of this?

Being able to use material in components with ShadowDom opens a lot of opportunities and cleaner components/code/CSS.

We are now in 2024 and as far as I can tell Angular Material is still not supported with encapsulation ShadowDOM. I was following the statement that css has to be loaded inside the shadow root but without any impact. Component was still not rendered correctly.

bramdonem commented 4 months ago

Is there any chance to get some perspective on this? For our enterprise applications it is really causing issues and we are considering migrating away from angular material!

It is starting to feel like this might never come?

davitenium commented 3 months ago

Hello,

It would be nice to have this support for our web components. ..Bump..

Nono2031 commented 3 months ago

Bump ! Waiting for Shadow DOM support.

Andrew-Marks-Trisept commented 3 months ago

It kind of seems to me like two major Angular features (Angular Material and Angular Elements) do not work correctly together. At least assuming ShadowDom encapsulation is used -- and it really seems like most people would want that on their generated web components, unless I'm missing something.

Anyway, we just finished converting to the MDC Material components, and this issue is actually worse now.

Background: We take a component from our app and use a second project/build to "export" it as a web component (via Angular Elements) so that other sites can use it. This uses ShadowDom encapsulation because obviously we want it isolated when running elsewhere. We take the app's main styles.scss (where Material is imported) and pull it into the exported component directly. This causes all the main styles, including Material stuff, to be present in a <style> node inside the #shadow-root.

This was working, but now with MDC it seems like a lot of the styling is defined via global CSS variables in rules like this:

html {
    --mat-divider-color: rgba(0, 0, 0, 0.12);
    --mat-expansion-container-background-color: white;
    --mat-expansion-container-text-color: rgba(0, 0, 0, 0.87);
    --mat-expansion-actions-divider-color: rgba(0, 0, 0, 0.12);
    --mat-expansion-header-hover-state-layer-color: rgba(0, 0, 0, 0.04);
    --mat-expansion-header-focus-state-layer-color: rgba(0, 0, 0, 0.04);
    --mat-expansion-header-disabled-state-text-color: rgba(0, 0, 0, 0.26);
    --mat-expansion-header-text-color: rgba(0, 0, 0, 0.87);
    --mat-expansion-header-description-color: rgba(0, 0, 0, 0.54);
    --mat-expansion-header-indicator-color: rgba(0, 0, 0, 0.54);
    --mat-expansion-header-collapsed-state-height: 48px;
    --mat-expansion-header-expanded-state-height: 64px;
    --mat-icon-color: inherit;
  }

These styles are not accessible by the component in the shadow DOM, resulting in broken style on all the Material controls. If we could just change the html selector to :host, it would work perfectly for our case.

Getting desperate to find any workaround besides creating our own separate, hardcoded copy of those CSS variables...


Edit: as @MirkoAdolph pointed out, the Angular docs say:

Angular Material assumes that, by default, all theme styles are loaded as global CSS. If you want to use Shadow DOM in your application, you must load the theme styles within each shadow root that contains an Angular Material component. You can accomplish this by manually loading the CSS in each shadow root, or by using Constructable Stylesheets.

It appears loading the theme styles within each shadow root no longer works. I'll admit I don't understand Constructable Stylesheets well enough to know if that is an option for SCSS provided by Angular Material that we don't control.

Andrew-Marks-Trisept commented 3 months ago

Now with MDC it seems like a lot of the styling is defined via global CSS variables ... These styles are not accessible by the component in the shadow DOM, resulting in broken style on all the Material controls.

If anyone is stuck on the same problem, we addressed it with an ugly hack that modifies the style nodes at runtime:

//Find all <style> elements inside the current component's shadow root
let styleElements = this.elementRef.nativeElement.shadowRoot.querySelectorAll('style');

//Replace relevant instances of "html{" or ":root{" with ":host{"
styleElements.forEach((styleElement: Element) => {
  if (styleElement.textContent) {
    styleElement.textContent = styleElement.textContent.replace(/html{--mat/g, ':host{--mat'); //e.g. "html{--mat-divider-color: rgba(0, 0, 0, 0.12); ..."
    styleElement.textContent = styleElement.textContent.replace(/html{--mdc/g, ':host{--mdc'); //e.g. "html{--mdc-filled-text-field-caret-color: #25c9d0; ..."
    styleElement.textContent = styleElement.textContent.replace(/html .mat-/g, ':host .mat-'); //e.g. "html .mat-mdc-form-field.mat-accent { ..."
    styleElement.textContent = styleElement.textContent.replace(/:root{--mat/g, ':host{--mat'); //e.g. ":root{--mat-select-panel-background-color: white; ..."
    styleElement.textContent = styleElement.textContent.replace(/:root{--mdc/g, ':host{--mdc'); //e.g. ":root{--mdc-filled-text-field-caret-color: #25c9d0; ..."
    styleElement.textContent = styleElement.textContent.replace(/:root .mat-/g, ':host .mat-'); //e.g. ":root .mat-mdc-form-field.mat-accent { ..."
  }
});