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

17,024

Solution 1

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

Solution 2

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.

Share:
17,024
None
Author by

None

Updated on August 01, 2022

Comments

  • None
    None almost 2 years

    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 :)

  • None
    None over 6 years
    can u please tell me why do i need this encapsulation? I mean this is working but i want to know why do i need to use this ?
  • None
    None over 6 years
    problem is that some other css classes not working then
  • Vega
    Vega over 6 years
    Component styles are protected and won’t bleed into other components. encapsulation defines if the styles from the component can affect the whole application or vice versa. It can have three values, None tells Angular that style set in component css can propagate back to the main HTML
  • Vega
    Vega over 6 years
    In both cases, the change is 'definitif' if you don't set afterwards they will persist
  • Chaos Crafter
    Chaos Crafter about 5 years
    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 Encapsulation" enabled view