Search code examples
angularshadow-dom

Style html,body from web component (Angular 2)


I'm working on a LoginComponent in Angular 2 that should "restyle" the html and body tags, so I can put in a background image specific for the login page.

But just adding a style for the html, body in my login.css doesn't seem to work.

Is there a way to override the style on the html, body from a component? Or any element for that matter.

I've tried things like:

:host(.btn) { ... }
:host(.btn:host) { ... }
.btn:host { ... }

to style an element from outside the Login component. But nothing seems to work.


Solution

  • You could try

    body {
      /* body styles here */
    } 
    

    but styles in components are not supposed to be applied to elements outside themselves.

    Another way is to use body as selector in your main component and use host-binding to set/remove a CSS class on body to make CSS you added to your index.html match.

    @Component({
      selector: "body", 
      host: {
        "[class.some-class]":"someClass" 
      }, 
    }) 
    export class AppComponent {
      constructor(private loginService: LoginService) {
        loginService.isLoggedInChanged.subscribe((value) => {
          this.someClass = value;
        });
      }
      someClass: bool = false;
    } 
    

    when you set someclass to true (usind some binding to a service, the class gets added to the body.

    If you don't want to add CSS globally you can also bind to a style attribute directly

    @Component({
      selector: "body", 
      host: {
        "[style.background-image]":"bodyBackgroundImage()" 
      }, 
    }) 
    export class AppComponent {
      bool isLoggedIn = false;
      constructor(private loginService: LoginService) {
        loginService.isLoggedInChanged.subscribe((value) => {
          this.isLoggedIn = value;
        });
      }
      function bodyBackgroundImage() {
        return this.isLoggedIn ? 'url("gradient_bg.png")': 'none';
      }
    } 
    

    update

    DomAdapter is gone. Renderer2 should provide similar functionality.

    A way to style <body> directly from the login component is to use the DomAdapter (see also https://github.com/angular/angular/issues/4942)

    System.import('angular2/src/platform/browser/browser_adapter').then(function(browser_adapter) {
      browser_adapter.BrowserDomAdapter.makeCurrent();
    })
    ...
    _dom: DomAdapter = new BrowserDomAdapter();
    _dom.setStyle(_dom.query('body'), 'padding', '50px');