Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change <body> tag style from child component?

I have this in index.html:

<body class="light-gray">
    <app-root></app-root>
    <div id="preloader">
        <div></div>
    </div>
</body>

In app-root i have this:

<laylout></laylout>

Inside layout i have one component where in scss i want to change body on index. Any suggestion how can i do that?

.light-gray{
    background: red!important;
}

I tried :host but this is not main parent i need something like: :host :host :host. Host of host of host :)

like image 631
None Avatar asked Oct 27 '17 10:10

None


2 Answers

Use ::ng-deep, like so:

CSS

::ng-deep .light-gray{
  background-color: red;
}

DEMO


Use ViewEncapsutation.None:

CSS

.light-gray{
    background-color:red
} 

Class:

import { ViewEncapsulation } from '@angular/core';
...
@Component({
...
encapsulation: ViewEncapsulation.None

DEMO

like image 71
Vega Avatar answered Nov 09 '22 03:11

Vega


To expand a little, View Encapsulation is the default, and it wraps all CSS defined within a view with extra selectors that limit it to only applying within the base object of the view.

It does this (from memory - may not be exactly correct) by adding an attribute to tags in that view (_ng_content-* being the usual format) and then modifying all the embedded CSS attached to the view to add a condition of [_ng_content-*]

So, for example, A view with view encapsulation enabled might be allocated the attribute "_ng_content-c2". As a result if its html was

<div class='mydiv'></div>

It would render as

<div _ng_content-c2 class='mydiv'></div>

and if the css for the view had

div.mydiv {color:black} 

then the style block with the div would be

div.mydiv[_ng_content-c2] {color:black}

So if you add a body css entry

body {color:black}

it renders as

body[_ng_content-c3] {color:black}

and as a result avoids actually changing your body tag (because your body tag won't have that attribute)

View encapsulation is very useful for allowing clean class names in objects without worrying about namespace collision. It's particularly relevant for shared components where you can't be sure your class names aren't used elsewhere.

On the other hand it makes lots of standard CSS difficult or impossible.

Personally I just don't use it, and prefer to use singular central css files for the whole document, but I'm not suggesting that is best practice.

For those that are interested, here is one of the issues with view encapsulation... If you have an encapsulated view within another encapsulated view it can be impossible for the outer views CSS to control the inner view as it will wrap it's CSS with the outer attribute, but the items in the inner view will have the inner attribute.

A possible fix to angular for this (but I'm not sure of its consequences) would be that inner views should have both their parents attribute as well as their own. This would become ugly though as the view stack grew.

Another feature I'd love to see would be a way to mark CSS items as not to be encapsulated or to only be "base encapsulated" (that being, encapsulation that only checked they existed within the base object where the CSS was, not that they were themselves created in the base object. That way you could have css like this...

div.taginbase {}
@noEncaps body {}
@baseEncaps div.taginchild

and this would render in the style tag as

div.taginbase[_ng_content_c] {}
body {}
[_ng_content_c] div.taginchild

This would then allow a view to define specific (and context aware) styling of view encapsulated child views.

like image 36
Chaos Crafter Avatar answered Nov 09 '22 03:11

Chaos Crafter