Skip to the solution
MediumFrontend9 min read

What is the difference between component styling using :host, :host-context, and ::ng-deep?

527 views

The problem

Question presented to candidate: "In a component stylesheet, what do :host, :host-context() and ::ng-deep each target? Show me how you would theme a panel for dark mode and restyle a library chip inside it, and tell me what Angular turns those selectors into."

What a strong answer should cover:

  • :host targets the component's own host element (which a template selector cannot reach); :host(.active) adds a condition on the host itself.
  • :host-context(.dark) applies when the host or any ancestor matches .dark; handy for themes set on body or a wrapper.
  • ::ng-deep turns off encapsulation for the rest of the selector, so it reaches into child components (and, without a prefix, the whole page).
  • With Emulated encapsulation Angular compiles them to attribute selectors: :host to [_nghost-…], :host-context(.dark) h3 to two selectors (.dark[_nghost-…] h3[…] and .dark [_nghost-…] h3[…]), ::ng-deep drops the _ngcontent requirement after it.
  • Always prefix ::ng-deep with :host to keep it inside your subtree; it is discouraged by the Angular docs and kept for backwards compatibility; prefer CSS custom properties or inputs.
  • Specificity still matters: a ::ng-deep rule can tie with the child's own rule and lose on order.

Clarifying questions expected:

  • "Do we own the child component, or is it a third-party library?"
  • "Is dark mode a class on body, on a wrapper, or a media query?"

Code / implementation expected: Yes β€” a panel using all three, with the compiled CSS shown.

  • styles
  • css

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

9 min read Β· 8 sections

Read the code

Angular:host, :host(.active), :host-context(.dark) and :host ::ng-deep with the CSS Angular generates
import { Component, afterNextRender, signal } from "@angular/core";

// A child we do not own (think: a library component) with its own emulated styles.
@Component({
  selector: "lib-chip",
  template: `<span class="chip-text">library chip</span>`,
  styles: `.chip-text { color: rgb(128, 128, 128); }`,
})
export class LibChip {}

@Component({
  selector: "themed-panel",
  imports: [LibChip],
  host: { "[class.active]": "active()" },
  template: `
    <h3>Panel title</h3>
    <button (click)="active.set(!active())">toggle .active on host</button>
    <lib-chip />
  `,
  styles: `
    :host { display: block; padding: 4px; }
    :host(.active) { outline: 2px solid rgb(0, 0, 255); }
    :host-context(.dark) h3 { color: rgb(255, 255, 255); }
    h3 { color: rgb(0, 0, 0); }
    /* lib-chip is in the selector on purpose: see the specificity note in the answer */
    :host ::ng-deep lib-chip .chip-text { color: rgb(255, 0, 0); }
  `,
})
export class ThemedPanel {
  active = signal(false);
}

@Component({
  selector: "app-root",
  imports: [ThemedPanel],
  template: `
    <button id="theme" (click)="dark.set(!dark())">toggle .dark on wrapper</button>
    <section [class.dark]="dark()"><themed-panel /></section>
    <pre>{{ css() }}</pre>
  `,
})
export class AppComponent {
  dark = signal(false);
  css = signal("");

  constructor() {
    // Show the rewritten CSS that Angular generated for themed-panel.
    afterNextRender(() => {
      const panelCss = [...document.head.querySelectorAll("style")]
        .map((s) => s.textContent ?? "")
        .find((t) => t.includes("outline"));
      this.css.set((panelCss ?? "").replace(/\}\s*/g, "}\n").trim());
    });
  }
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 51 of 121 in Angular

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Angular questions
Up nextMedium

What is the difference between Observables and Promises?

Continue