I have a Home component inside it I have a carousel component. I would like to apply background color of home as Gray and background color of the carousel as blue.
I am unable to apply a background color to the body tag of Home component.
Angular 2 is all about modularity so it purposefully adds a css scope to all of your styles in a component so that a parent's component's styles don't bleed through and affect the way that a child component looks. Thats why all of your components have that weird attribute that looks like this: _ngcontent-c0
If you look at the css that was generated for your component, you'll also notice that this tag has been added to all of your styles: h1[_ngcontent-c0]
So your Home and Carousel components would need their own styles:
#Component({
selector: 'home',
template: `<body>
<carousel></carousel>
</body>`,
styles: ['body { background-color: gray; }']
})
#Component({
selector: 'carousel',
template: `<div id="carousel_body">
<!-- carousel stuff here -->
</div>`,
styles: ['#carousel_body{ background-color: blue; }']
})
The other alternatives you have are:
Make the styles global by putting them in a css file that is referenced by your index.html in the traditional manner
Use a special selector such as :host or /deep/ to override the css scoping mechanism (/deep/ is deprecated)
You can set encapsulation: ViewEncapsulation.None on all of your components which disables the css scoping, but in my opinion, this defeats much of what makes angular great.
Each of these options are described in greater length here
Here's an example on plunkr
Related
I have some issue with my Angular web component.
My angular application contains the web component as a child, but the issue is the css of the child component is also applying to its parent.
For instance, in web component, there's some style on its body tag. However, it is also overriding the style of its parent. Is there any way to avoid this?
<div id="my-app">
<webcomponent></webcomponent>
</div>
If you have built your webcomponent with Angular Elements, you can make use of dom / style isolation by setting ViewEncapsulation to ShadowDom:
import { Component, ViewEncapsulation } from "#angular/core";
#Component({
selector: "webcomponent",
template: `
<h3>Webcomponent</h3>
`,
styleUrls: ["./webcomponent.css"],
encapsulation: ViewEncapsulation.ShadowDom
})
export class WebcomponentComponent {}
Please notice that by using shadow dom, you will also not be able to style html inside the component from outside the component.
I've used :host ::ng-deep successfully to achieve what you're looking for.
For the CSS inside web component, add :host ::ng-deep prior to your CSS element. Ex: :host ::ng-deep .my-class { color: blue }
From the docs, 'In order to scope the specified style to the current component and all its descendants, be sure to include the :host selector before ::ng-deep'
Docs: https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep
I have created a new Angular CLI project and a component where I have tried work on css specificity. Wherewer I tryed, class styles overwrite tag styles, but only on Angular project it's working vise versa
I have founded that ViewEncapsulation.None makes the css styles show darkgreen backgound-color and with the angular default view encapsulation (ViewEncapsulation.Emulated) browser shows aqua background-color.
component code
import { Component, OnInit } from '#angular/core';
import {ToastrService} from "ngx-toastr";
//import {ViewEncapsulation} from "#angular/cli/lib/config/schema";
#Component({
selector: 'app-toastr',
templateUrl: './toastr.component.html',
styleUrls: ['./toastr.component.css'],
//encapsulation: ViewEncapsulation.None
})
html code
<div>
<div class="myspan">
something
</div>
</div>
and styles
div div{
background-color: aqua;
}
.myspan {
background-color: darkgreen;
}
I expect to receive an answer why it works differently
FYI
ViewEncapsulation.Emulated: Any styles we define on a component don’t leak out to the rest of the application. But, the component still inherits global styles like twitter bootstrap.
ViewEncapsulation.Native: Styles we set on a component do not leak outside of the components scope. Component is also isolated from the global styles we’ve defined for our application.
ViewEncapsulation.None: We are not encapsulating anything, the style we defined in our component has leaked out and started affecting the other components.
We have an in-house Angular component library (one project), each component has basic styling.
We use this library in our App (another project).
A component in the App contains a component from our library.
From the global styles.scss in the App, I can target the elements in the library component just fine.
If I move that global CSS into the App component CSS file, try what may, I cannot target any elements inside the library component.
app-component.html
<div class="outter">
<library-component specificityattr></library-component>
</div>
library-component.html
<div class="generic-styles">
<p class="hello">Hello</p>
</div>
app-component.scss
library-component[specificityattr] p.hello {
background: red;
}
styles.scss
library-component[specificityattr] p.hello {
background: green;
}
Without the selector in styles.scss, I expect the P tag to have a red background.
Only when I put the same selector in styles.scss do I get a green background.
How is this failing?
What is the correct way to style a components sub-components?
Your :host component is th library-component and you want to apply css to some "deep" DOMS so it means :ng-deep
Here is working example
Use
:host library-component[specificityattr] ::ng-deep p.hello {
background: green;
}
What you are experiencing is an effect of the default ViewEncapsulation of components in Angular.
When you define a component such as below, the view encapsulation of the component will be the default value, which I've included inside a comment. This means that Angular won't create a so called 'shadow DOM' for your component, and all the styles will only be applied to your component.
Encapsulated component
#Component({
selector: 'my-component',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
//encapsulation: ViewEncapsulation.Emulated
})
If you instead want to apply the styles not only to your component, you can specify a specific ViewEncapsulation in your component declaration. Using ViewEncapsulation.None will move the styles to the DOM head, and it will still not create a shadow DOM.
Without encapsulation
#Component({
selector: 'my-component',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
encapsulation: ViewEncapsulation.None
})
Have a look at this StackBlitz example
It's important to keep in mind that ViewEncapsulation.None will "leak" your styles to other components, which in turn will make it harder to style your application unless you know exactly where your styles are defined.
I have an angular-cli app and using webpack.
When I try to run it the component specific css doesn't work
styles.css
/* You can add global styles to this file, and also import other style files*/
#import 'http://something/v4/dist/css/bootstrap.min.css';
Component
#Component({
selector: 'app-carousel',
templateUrl: './carousel.component.html',
styleUrls: ['./carousel.component.css']
})
export class CarouselComponent implements OnInit {
Component CSS
.carousel-indicators { display: none; }
angular-cli.config
"styles": [
"styles.css",
"../node_modules/roboto-fontface/css/roboto/sass/roboto-fontface-bold.scss",
"../node_modules/roboto-fontface/css/roboto/sass/roboto-fontface-light.scss",
"../node_modules/roboto-fontface/css/roboto/sass/roboto-fontface-regular.scss"
],
The rendered html
<style type="text/css">#import url(http://something/v4/dist/css/bootstrap.min.css);</style>
<style type="text/css">/* You can add global styles to this file, and also import other style files */
</style><style></style><style>.carousel-indicators[_ngcontent-c5] { display: none; }</style>
but this is not applied to my html element 'carousel-indicators'
If I import the carousel.component.cssinto the styles.css then it works but it appears twice in the generated html
I'm looking for the right way of doing this
By default(as in your case) angular using ViewEncapsulation.Emulated that scopes your css. However there is 3 view encapsulation options in Angular:
Native view encapsulation uses the browser's native shadow DOM implementation (see Shadow DOM on the MDN site) to attach a shadow DOM to the component's host element, and then puts the component view inside that shadow DOM. The component's styles are included within the shadow DOM.
Emulated view encapsulation (the default) emulates the behavior of shadow DOM by preprocessing (and renaming) the CSS code to effectively scope the CSS to the component's view. For details, see Appendix 1.
None means that Angular does no view encapsulation. Angular adds the CSS to the global styles. The scoping rules, isolations, and protections discussed earlier don't apply. This is essentially the same as pasting the component's styles into the HTML.
So when you applying any styles to your component in component.css(with default ViewEncapsulation.Emulated) the styles will be applied just for that particular component, it won't be leaked outside the component and always have a priority above the global styles unless global style has !important.
So as a result you have the style in the head of your html file like:
<style>.carousel-indicators[_ngcontent-c5] { display: none; }</style>
If you referencing your component.css in styles.css then it will became a global style rendered in html head like so:
<style type="text/css">/* You can add global styles to this file, and also import other style files */
.carousel-indicators {
display: none; }
</style>
As you declared you style in competent and then referenced your component.css in styles.css that competent styles just gets doubled in your html: one copy is a global style and other copy is scoped component styles.
I was tried to replicate you issue but my compentnt.css is always gets applied. I am using the latest stable angular cli 1.3.2. If you are using older cli try to update. Otherwise push your code on github or create a plunker so I can take a look.
UPDATE: You might have your custom css gets overridden by some of your global stylesheets you are referencing. You can use chrome dev tools to debug the styles also you can try to put !important to your custom css and see if it does help.
For everybody landing here :
The issue was with the ViewEncapsulation.Emulated I changed it to ViewEncapsulation.None as describe in this stackoverflow answer :
how to hide ngb-carousel indicators and prev-next control
Thanks for your help
Is there a way to stop global styles to bleed in to child components without ViewEncapsulation.Native?
For example I have a global style
.container {
background: green
}
and a component
#Component({
template: html,
styleUrls: [url],
selector: 'dynamic-lp',
encapsulation: ViewEncapsulation.Emulated
})
The component is a dynamically added component with variable styleUrls and template html, so I don't want to inherit the green background if the template has a .container class.
If I change ViewEncapsulation.Emulated to ViewEncapsulation.Native all works as expected, but I would like to know if there's another way to achieve what I want since Shadow Dom is not supported by most browsers yet
UPDATE
I've found a solution which is working for me.
Wrap your sass imports in a "body:not(...)" assignment like this
body *:not(.innerhtml-container) {
#import 'bootstrap';
#import 'someother-plugin';
/* Components */
#import 'components/loading-bar';
#import 'components/textfield';
}
And add a container class "innerhtml-container" around the component template.
For example:
<div class="innerhtml-container"><div class="container">...</div></div>
this way no css inheritance will be passed on to the child component