245

I have component in Angular 2 called my-comp:

<my-comp></my-comp>

How does one style the host element of this component in Angular 2?

In Polymer, You would use ":host" selector. I tried it in Angular 2. But it doesn't work.

:host {
  display: block;
  width: 100%;
  height: 100%;
}

I also tried using the component as selector:

my-comp {
  display: block;
  width: 100%;
  height: 100%;
}

Both approaches don't seem to work.

Thanks.

Munim Munna
  • 17,178
  • 6
  • 29
  • 58
Ravi Teja Gudapati
  • 2,809
  • 2
  • 13
  • 16

6 Answers6

336

There was a bug, but it was fixed in the meantime. :host { } works fine now.

Also supported are

  • :host(selector) { ... } for selector to match attributes, classes, ... on the host element
  • :host-context(selector) { ... } for selector to match elements, classes, ...on parent components

  • selector /deep/ selector (alias selector >>> selector doesn't work with SASS) for styles to match across element boundaries

    • UPDATE: SASS is deprecating /deep/.
      Angular (TS and Dart) added ::ng-deep as a replacement that's also compatible with SASS.

    • UPDATE2: ::slotted ::slotted is now supported by all new browsers and can be used with `ViewEncapsulation.ShadowDom
      https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted

See also Load external css style into Angular 2 Component

/deep/ and >>> are not affected by the same selector combinators that in Chrome which are deprecated.
Angular emulates (rewrites) them, and therefore doesn't depend on browsers supporting them.

This is also why /deep/ and >>> don't work with ViewEncapsulation.Native which enables native shadow DOM and depends on browser support.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 1
    `@Component({selector: 'some-selector', template: 'xxx', styles: [':host { display: block; background-color: green; border: solid 1px red; }']}) export class SomeClass {}` – Günter Zöchbauer Apr 18 '16 at 13:18
  • @OndraŽižka can you elaborate more? This is pure CSS, how can it be inconsistent with CSS and itself? – Günter Zöchbauer Feb 02 '17 at 04:34
  • Unless I have missed some important shift in CSS, /deep/ and >>> are not CSS. – Ondra Žižka Feb 02 '17 at 23:27
  • They are deprecated, but that doesm't matter. They are emulated by Angular (rewritten), therefore they only work with `ViewEncapsularion.Emulated` (default) but not with `Native`. – Günter Zöchbauer Feb 03 '17 at 04:02
  • In Angular 2.4.7 I am able to get `:host { p { font-size: 80%; } }` to work in a ...component.css file. As soon as I try to use it with `styles: [:host { p { font-size: 80%; } }]` it no-longer works. Very strange. – Martin Feb 16 '17 at 11:35
  • You missed the quotes `styles: [":host { p { font-size: 80%; } }"]` – Günter Zöchbauer Feb 16 '17 at 11:38
  • There is no difference in behavior between `styles` and `styleUrls` – Günter Zöchbauer Feb 27 '17 at 05:53
  • @GünterZöchbauer I am trying to use this to style a component like :host(.mine) { color: green; } but it dosent seem to work , when i put this in the parent component ccs file – Rahul Singh Mar 03 '17 at 15:04
  • What is "this" that you put at the parent component? When you add `class="mine"` at the component itself, it should make the color of the component green where you add it at. If you add `class="mine"` at a parent or ancestor component, you need to use `:host-context(.mine) { color: green; `. If you add `:host(.mine) { color: green; }` at the parent component, then you need to add `class="mine"` at the parent component and the stile will also address the parent component only. – Günter Zöchbauer Mar 03 '17 at 15:07
  • @GünterZöchbauer how can we access component variable inside host? If i want to decide background-color dynamically? ':host { background-color: this.bgColor; }' – Pratap A.K Mar 28 '18 at 08:35
  • @PratapA.K What is "component variable inside host"? – Günter Zöchbauer Mar 28 '18 at 08:38
  • In general, I have a variable inside my class "bgColorValue=red" and I want to set this value :host {background-color: this.bgColorValue} – Pratap A.K Mar 28 '18 at 08:42
  • @PratapA.K You can't access component variables from CSS. You can use `[style.backgroundColor]="bgColorValue"` on elements in your template or add `@HostBinding('style.backgroundColor')` before your `bgColorValue` variable – Günter Zöchbauer Mar 28 '18 at 08:46
  • @GünterZöchbauer thanks for the reply. having said that, is there a way to get css from the backend (100 classes css)? like in liferay? One of my component should provide a text box for the user to add css code and it should reflect in the component. – Pratap A.K Mar 28 '18 at 08:54
  • @PratapA.K sorry, don't think I can help you here. Perhaps better to create a new question with more details. – Günter Zöchbauer Mar 28 '18 at 08:56
  • @GünterZöchbauer could you please answer this https://stackoverflow.com/q/49530499/2742156 – Pratap A.K Mar 28 '18 at 09:14
58

I have found a solution how to style just the component element. I have not found any documentation how it works, but you can put attributes values into the component directive, under the 'host' property like this:

@Component({
    ...
    styles: [`
      :host {
        'style': 'display: table; height: 100%',
        'class': 'myClass'
      }`
})
export class MyComponent
{
    constructor() {}

    // Also you can use @HostBinding decorator
    @HostBinding('style.background-color') public color: string = 'lime';
    @HostBinding('class.highlighted') public highlighted: boolean = true;
}

UPDATE: As Günter Zöchbauer mentioned, there was a bug, and now you can style the host element even in css file, like this:

:host{ ... }
prespic
  • 1,635
  • 1
  • 17
  • 20
  • 1
    I like this better than creating a dummy .root element, but I don't like that it sets these styles as inline (forcing a `!important` to override). There's got to be a better waayy :\ – Scrimothy Mar 18 '16 at 14:06
  • 4
    no, styling via `host{}` in a `stylesUrl` file does not work. needs `:host`. – phil294 Dec 29 '16 at 21:23
  • how can we access component variable inside host? If i want to decide background-color dynamically? ':host { background-color: this.bgColor; }' – Pratap A.K Mar 28 '18 at 08:36
  • @PratapA.K Hi, you can use HostBinding derorator. You example will be: `@HostBinding('style.background-color') private color = 'lime';` Google will find you many examples and articles. – prespic Mar 28 '18 at 14:59
  • That helped a lot .Thanks – Arun s Nov 24 '21 at 13:37
12

Check out this issue. I think the bug will be resolved when new template precompilation logic will be implemented. For now I think the best you can do is to wrap your template into <div class="root"> and style this div:

@Component({ ... })
@View({
  template: `
    <div class="root">
      <h2>Hello Angular2!</h2>
      <p>here is your template</p>
    </div>
  `,
  styles: [`
    .root {
      background: blue;
    }
  `],
   ...
})
class SomeComponent {}

See this plunker

alexpods
  • 47,475
  • 10
  • 100
  • 94
11

In your Component you can add .class to your host element if you would have some general styles that you want to apply.

export class MyComponent{
     @HostBinding('class') classes = 'classA classB';
HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
Xquick
  • 637
  • 1
  • 8
  • 20
6

For anyone looking to style child elements of a :host here is an example of how to use ::ng-deep

:host::ng-deep <child element>

e.g :host::ng-deep span { color: red; }

As others said /deep/ is deprecated

Petros Kyriakou
  • 5,214
  • 4
  • 43
  • 82
3

Try the :host > /deep/ :

Add the following to the parent.component.less file

:host {
    /deep/ app-child-component {
       //your child style
    }
}

Replace the app-child-component by your child selector

abahet
  • 10,355
  • 4
  • 32
  • 23