0

In Angular 7 - How do I style HTML thats projected using ng-content.

Tech: Angular 7, Angular CLI, SASS, HTML5, Webpack.

My Code:

Note: my component html with transclusion / projection. This component has a scss file and the html that comes through the ng-content can only be styled if ng-deep is used e.g. :host::ng-deep

<table>
  <ng-content></ng-content>
</table>

This is my sass for the above components html:

:host::ng-deep {
  table {
    background-color: map-get($theme-brand, flat);
    display: flex;
    flex-direction: column;
    border: 1px solid map-get($theme-contrast, contrast-8);
    border-radius: 5px;

    tr {
      display: flex;
      justify-content: flex-end;
    }

    th, td {
      @extend %p-2;
      word-break: break-all;
      align-items: center;
      display: flex;
      text-align: right;
      width: 250px;
      color: map-get($theme-typography-color, regular);

      &:first-child {
        text-align: left;
        border: none;
        width: 100%;
      }
    }
  }
}

Note: So the above css for tr and th, td won't get styled due to the projection preventing the styling unless I use the ng-deep.

Things tried:

  • ng-deep (which works but don't want to use as its deprecated soon by browsers).
AngularM
  • 15,982
  • 28
  • 94
  • 169
  • 5
    the deprecated thing is true but idk when is taking place. I have heard of that since angular 4 lol – Patricio Vargas May 12 '19 at 16:09
  • Possible duplicate of [Right way to override child component style from host component angular](https://stackoverflow.com/questions/54328837/right-way-to-override-child-component-style-from-host-component-angular) – Reactgular May 12 '19 at 17:59

1 Answers1

1

According to this question, you have two different approaches:

1: Use the ::slotted pseudo selector, which is starting to be supported by new browsers. To use that, you will need to change the encapsulation property of @Component to ViewEncapsulation.ShadowDom.

2: A kind of brute force approach, which is setting the encapsulation property of @Component to ViewEncapsulation.None. This way, the style will be applied to all the page, without being processed by Angular.

You can check more details about ViewEncapuslation here: https://angular.io/api/core/ViewEncapsulation

There is also a discussion in Github about that.

  • Apparently ShadowDom is buggy when styling in Safari for slotted option. And for ViewEncapsulation.None isnt an option for me due to scope bleeding of the css – AngularM May 12 '19 at 17:39
  • 1
    There is nothing *brute force* about `ViewEncapsulation.None`. It's the proper *setting* when you need a component's view to be styled in the *global* scope of CSS. It's not a big deal to use it when you need it. – Reactgular May 12 '19 at 18:07
  • @cgTag For sure. It is just for emphasizing that it needs to be done cautiously, as you are dealing with global styles. But, as you said, it is a great solution for some cases. – Christian Valentin May 12 '19 at 19:54