6

The way I see it, it could be used as a replacement for <div> containers for styling a component. Example:

Using container

@Component({
    template: `
        <div class="container">
            <h1>Some Title</h1>
            <p>Some Content</h1>
        </div>
    `,
    styles: [`
        .container {
            border: 1px solid black;
            display: flex;
        }
    `],
})

Using :host

@Component({
    template: `
      <h1>Some Title</h1>
      <p>Some Content</h1>
    `,
    styles: [`
        :host {
            border: 1px solid black;
            display: flex;
        }
    `],
})

If I understand correctly, these two solve the exact same problem. And it's nice to have one less element and class to worry about in pretty much every single component.

Questions: Is this what :host is intended for? If not, what is the point of it, and what are the best practices for giving style to your component aside from adding containers everywhere?

P.S.
  • 15,970
  • 14
  • 62
  • 86
Frigo
  • 284
  • 4
  • 15
  • You are right. :host can be used to apply any style to the current component. You can use a wrapper and write styles for it too. So it is just a matter of preference and based on your requirement. If it is just a wrapper then you can straight away go for `:host`. – Kiran Dash Sep 27 '17 at 13:05
  • @KiranDash It's not a matter of preference, setting styles on host can define the default `display` property of the component which is `inline` by default and putting block elements inside inline ones make no sense IMHO. – n00dl3 Sep 27 '17 at 13:07

3 Answers3

3

They don't solve the same problem. :host is for styling the host and the .container is for styling any div that has the container class inside your component.

The .container div will not be available for styling outside of your component due to encapsulation while the host element can be styled.

Note that the initial value of the display property is inline, so by default your component will be displayed as an inline element. Maybe you don't want that, especially if you have a block element inside of it which might seem counter-intuitive (even if it's allowed).

n00dl3
  • 21,213
  • 7
  • 66
  • 76
  • 1
    I guess they are not equivalent, but surely they solve the same problem in my example (where I assume only one instance of `.container` that wraps everything else in my template)? Good point about `display`, though! That's definitely a side-effect I hadn't considered. Also what @AdrianMoisa mentioned about encapsulation. I'm still not sure what the point of the `:host` selector is, if not for styling things that would otherwise go into a `.container`/`.wrapper`/`my-component-name`/`#whatever`. – Frigo Oct 02 '17 at 12:32
  • You cannot style `.container` from outside your component (except using deprectated `/deep/` selector). You can style the host element though. So styling the host element allows you to put default styles on your component. – n00dl3 Oct 02 '17 at 12:54
0

:host is styling your wrapper element for the current component (for example <app-header> element), and as I know, it's a short and comfortable way to style elements like this.

P.S.
  • 15,970
  • 14
  • 62
  • 86
  • How do I use `:host` for a specific `
    ` class in that component's html
    – Ayush Kumar Feb 12 '19 at 11:24
  • @AyushKumar If I understood you correctly, it should be something like `:host .abc { background-color: green; }` or `:host ::ng-deep .abc { background-color: green; }` for some specific cases. – P.S. Feb 12 '19 at 13:07
  • What I meant was that :host does the binding for the entire component. What if I want to apply to a specific class of a div within that component. For example, I have 2 div in a component and I want to toggle only div1 using hostbinding's :host selector – Ayush Kumar Feb 13 '19 at 08:23
  • https://stackblitz.com/edit/angular-communication-3 For example, In the side-bar.component.html if there are 2 div and I want to toggle only 1 div with a click – Ayush Kumar Feb 13 '19 at 08:27
  • @AyushKumar I don't see any `div`s in `side-bar.component.html` or `side-bar-toggle.component.html`. – P.S. Feb 13 '19 at 08:34
  • I meant that if I create 2 div there and want to toggle only one. Something like that – Ayush Kumar Feb 13 '19 at 09:27
0

I will also add the following observations to the current answers:

class .container

  • If you use class .container than you have to always keep them in sync in case you desire to rename your components. In large apps this tends to happen often in the early stages of development.
  • Also this leaves you open for name collisions especially if you don't have good CSS hygiene habits.
  • It can be mistakenly deleted at run-time by overwriting the element class property. Use element.classList.add(); .remove()

:host

  • spares you the need of a lot of typing (sometimes component names can get long)
  • It is there no matter what classes you add to the element. I believe it must also have precedence over the .container class.
  • (Angular only) Angular emulates same behavior, but if you disable component encapsulation all :host selectors become useless which can lead to the use of .container class.
Adrian Moisa
  • 3,923
  • 7
  • 41
  • 66