cssangularcomponentsparent-childrouter-outlet

Styling angular material components from child components


HomeComponent templates includes a router outlet

/* home.component.ts */
...
<mat-sidenav-container>
<mat-sidenav-content>
        <router-outlet></router-outlet>
    </mat-sidenav-content>
</mat-sidenav-container>

that will render a ListComponent which style should set the overflow of mat-sidenav-content.

Why is the following not working?

/* list.component.css */
:host-context(mat-sidenav-content) { /* same for .mat-sidenav-content */
    overflow: unset !important;
}

From my understanding the selector should pick any mat-sidenav-content traversing all the DOM to the root.


Solution

  • I'm afraid this isn't how :host-context works. Host context is for applying styles to the component host conditionally based on it's ancestors. In your example the list component should have overflow: unset but if there was another instance of it without mat-sidenav-content as an ancestor it would not have this. This can be useful for applying styles based on a theme as shown in the documentation here:

    https://angular.io/guide/component-styles#host-context

    I have included an example on stackblitz with your overflow css and I also set the text to be red in that case so it's more obvious and you can see how it applies to one and not the other. Unfortunately there is not a way to do what I believe you are trying to do which is apply a style to a parent when the component is inside that parent.

    The example I have also has ::ng-deep in the other component for completeness, as I have seen used to apply styles to other components by some. I would recommend you stay away from this as well as this style will remain after being first applied(try going to that link and then back to list) and ::ng-deep is deprecated anyway.

    https://stackblitz.com/edit/angular-material-sidenav-generate-nav-5fvfjq?file=src/app/list/list.component.css

    Edit: The stackblitz has been updated to include an example of :host

    It's better to think of the host element in HTML terms rather than as a component, so in the dom <app-list> is the host element rather than what's in the template. If you wanted to style stuff in there you wouldn't need to use :host. I've updated my stackblitz example to include host and if you inspect the css you might get a better idea of how it works.

    The HTML looks like this

    <app-list _nghost-qnl-c20="">
      <p _ngcontent-qnl-c20=""> This text should be red only when inside mat-sidenav-content. The font family is set by host.
      </p>
    </app-list>
    

    And the css:

    mat-sidenav-content[_nghost-qnl-c20], mat-sidenav-content [_nghost-qnl-c20] {
        color: red;
    }
    [_nghost-qnl-c20] {
        font-family: Arial, Helvetica, sans-serif;
    }
    

    So you can see that host uses an attribute generated by angular and :host by itself is simply that attribute and :host-context(element) becomes element [attribute] in the css.