React style element descendant selector - css

I want to use the direct descendant CSS selector in a React inline style element:
<style>{`
.something>div{
color: blue;
}
`}</style>
This is working fine on dev but in prod, React (un)helpfully converts the > into a gt;, screwing up my CSS.
How can I do a direct descendant in a React inline style element?
Alternatively, how can I get React to treat the innerHTML as literal?
I have a React app with multiple files and pages using Gatsby, which is notorious for not allowing multiple different CSS for different pages. I'm also using nested React components, so giving the nested components classes is not an option without modifying node_modules.

Try styled-components, you can write style like native css with it.
e.g.
import styled, { css } from 'styled-components'
const ToTop = styled.button`
position: fixed;
right: 10px;
bottom: 10px;
polyline {
stroke:#000;
${otherStyles}
}
&: hover{
background: #dcc9c9;
}
`
export default () => (
<ToTop />
)
About InnerHTML, see this doc

If you're insisting on using child selectors in CSS with style tags, you can use the dangerouslySetInnerHTML property of a jsx (in this case, style) element:
<style dangerouslySetInnerHTML={`
div>p{
color:blue;
}
`}/>

Related

Why :host-context is required when :host can suffice the needs in Angular

As I understand :host-context is used to apply styles based on selector of parent.
Lets consider a rule as follows:
:host-context(.red-theme) { background-color: red; }
same can be written using :host selector as folows:
.red-theme :host { background-color: red; }
Then whh is host-context explicitly required?
Use :host if you want to style the component custom HTML element itself.
Where as :host-context is used when you also want to have a component apply a style taking into account context in which component is rendered.
So for example, you could do: (with host-context)
<div class="red-theme">
<app-component></app-component>
</div>
where app-component
<button class="btn btn-theme">Button</button>
and the component style is defined:
:host-context(.red-theme) .btn-theme {
background: red;
}
Useful if you want to have multiple alternative themes on your web application.
:host and :host-context are not Angular features, but CSS features.
Within the demo provided at stackblitz.com/edit/angular-z3xxtu, the Angular components are merged into the DOM and allow plain old CSS selector structure like .parent :host .child { color: red; }.
This changes when using Webcomponents and ShadowDOM.
The ShadowDOM acts as a barrier and encapsulates the contained markup and style, so the .parent cannot style the things on the :host and vice versa. Note cannot is not totally true, see ::part and CSS Custom Properties.
With a structure like <parent> <my-component> ShadowDOM <child> the above CSS rule no longer works and :host-context(.parent) (which could be read as .parent :host) is needed. Sadly as of 2023-01-10 this doesn't work in Firefox and Safari.
In the above demo, :host-context(.red) { color: red; } and .red :host { color: red; } produce the same output because there's no ShadowDOM involved. On top of that, Angular transforms the invalid .test :host in the CSS to .test [_nghost-some-id] which is a valid CSS selector.

Working with nested selectors & vuejs css modules

Is it possible to work with nested css selectors when using vuejs css modules?
For example, I want to scope this css (so that id does not affect child components):
.list {
...
.item {
...
}
}
In the documentation I could see only not-nested examples, but is it at all convenient, since I'll need then name them like .list-item which resembles BEM. But if I use BEM there is no point in using css modules, is there?
Yes, it's possible to work with nested css selectors so they will not affect child components; use css modules.
You need to use a preprocessor to enable nesting, either LESS or SASS.
If using Single File Components your component would look something like this
<template>
<ul :class="$style.list">
<li :class="$style.item"></li>
</ul>
</template>
<!-- Or lang="less" -->
<style module lang="scss">
.list {
...
.item {
...
}
}
</style>
Yes, nesting css selectors is called using scss. You will have to setup scss.
Example make your style tag in the vue component:
<style scoped lang="scss">
The scoped attribute tells it to apply only to this component.
In regards to bem you can do stuff like this in scss:
.list {
//styles-a
&-item {
//styles-b
}
}
which will convert to this in css:
.list {
//styles-a
}
.list-item {
//styles-b
}
If you want, for example, override CSS class of some UI library in Vue you can use :global keyword. Let's say you have a n-dropdown component from Naive UI library. And you want to customize it with overriding its native very deeeeeply nested n-dropdown-option-body__prefix--show-icon CSS class only in current component using CSS modules. Here is how you can do it:
<template>
<n-dropdown :class="$style.menu">
</n-dropdown>
</template>
<style module>
.menu:global.n-dropdown-menu .n-dropdown-option .n-dropdown-option-body .n-dropdown-option-body__prefix.n-dropdown-option-body__prefix--show-icon {
margin-left: 33px;
margin-right: 19px;
}
</style>
In the end you will get selector which looks something like this
.MobileNavMenu_menu_NhSka.n-dropdown-menu .n-dropdown-option .n-dropdown-option-body .n-dropdown-option-body__prefix.n-dropdown-option-body__prefix--show-icon {
margin-left: 33px;
margin-right: 19px;
}
So all classes after :global keyword will be untouched by module manipulations.
If .n-dropdown-menu should be a child of menu then :global should have a whitespace from both sides:
.menu :global .n-dropdown-menu
Vue will remind you about it with horrible crash

Angular2: styling component dynamically inserted by the router

Searched for an answer for this and saw people struggling with this but no direct answer, especially with regards to the released 2.x version of Angular.
Suppose you have app.component.html with the following code:
<div>
<router-outlet></router-outlet>
</div>
The router dynamically inserts your custom component, say my-component and (strangely enough) places that component as a sibling of router-outlet element like so:
<div>
<router-outlet></router-outlet>
<my-component></my-component>
</div>
Obviously, the router can place another component in there, so you can't rely on the name being my-component when creating styles in your app.component.css file.
So... How do you do this?
Why this matters? Why not just set the styles on the :host inside of the my-component CSS? Well, because not all styles belong there. For example, if the app.component decides that it's a flex container (i.e., display: flex;), that would mean that the my-component element should be styled as a flex item (i.e., flex: 1 0 0;). Placing the flex item style inside of the my-component seems like a bad practice because you are coupling it with the style of its parent component.
Chime in if you know the answer.
Thanks!
I haven't tried but I guess the adjacent sibling selector should allow you to do that
:host div + * {
display: flex;
}
The key is /deep/ keyword:
the style will apply to whatever element followed by router-outlet.
Or make it specific to apply different style to known components.
:host /deep/ router-outlet + my-component {
display: block;
border: 10px solid black;
}
:host /deep/ router-outlet + my-component2 {
display: block;
border: 10px solid red;
}

How to style child components from parent component's CSS file?

I've got a parent component:
<parent></parent>
And I want to populate this group with child components:
<parent>
<child></child>
<child></child>
<child></child>
</parent>
Parent template:
<div class="parent">
<!-- Children goes here -->
<ng-content></ng-content>
</div>
Child template:
<div class="child">Test</div>
Since parent and child are two separate components, their styles are locked to their own scope.
In my parent component I tried doing:
.parent .child {
// Styles for child
}
But the .child styles are not getting applied to the child components.
I tried using styleUrls to include the parent's stylesheet into child component to solve the scope issue:
// child.component.ts
styleUrls: [
'./parent.component.css',
'./child.component.css',
]
But that didn't help, also tried the other way by fetching the child stylesheet into parent but that didn't help either.
So how do you style child components that are included into a parent component?
Update - Newest Way
Don't do it, if you can avoid it. As Devon Sans points out in the comments: This feature will most likely be deprecated.
Last Update
From Angular 4.3.0 till even now (Angular 12.x), all piercing css combinators were deprecated. Angular team introduced a new combinator ::ng-deep as shown below,
DEMO : https://plnkr.co/edit/RBJIszu14o4svHLQt563?p=preview
styles: [
`
:host { color: red; }
:host ::ng-deep parent {
color:blue;
}
:host ::ng-deep child{
color:orange;
}
:host ::ng-deep child.class1 {
color:yellow;
}
:host ::ng-deep child.class2{
color:pink;
}
`
],
template: `
Angular2 //red
<parent> //blue
<child></child> //orange
<child class="class1"></child> //yellow
<child class="class2"></child> //pink
</parent>
`
Old way
You can use encapsulation mode and/or piercing CSS combinators >>>, /deep/ and ::shadow
working example : http://plnkr.co/edit/1RBDGQ?p=preview
styles: [
`
:host { color: red; }
:host >>> parent {
color:blue;
}
:host >>> child{
color:orange;
}
:host >>> child.class1 {
color:yellow;
}
:host >>> child.class2{
color:pink;
}
`
],
template: `
Angular2 //red
<parent> //blue
<child></child> //orange
<child class="class1"></child> //yellow
<child class="class2"></child> //pink
</parent>
`
You should NOT use ::ng-deep, it is deprecated. In Angular, the proper way to change the style of children's component from the parent is to use encapsulation (read the warning below to understand the implications):
import { ViewEncapsulation } from '#angular/core';
#Component({
....
encapsulation: ViewEncapsulation.None
})
And then, you will be able to modify the css form your component without a need from ::ng-deep
.mat-sort-header-container {
display: flex;
justify-content: center;
}
WARNING: Doing this will make all css rules you write for this component to be global.
In order to limit the scope of your css to this component and his child only, add a css class to the top tag of your component and put your css "inside" this tag:
template:
<div class='my-component'>
<child-component class="first">First</child>
</div>,
Scss file:
.my-component {
// All your css goes in there in order not to be global
}
UPDATE 3:
::ng-deep is also deprecated which means you should not do this at all anymore. It is unclear how this affects things where you need to override styles in child components from a parent component. To me it seems odd if this gets removed completely because how would this affect things as libraries where you need to override styles in a library component?
Comment if you have any insight in this.
UPDATE 2:
Since /deep/ and all other shadow piercing selectors are now deprecated. Angular dropped ::ng-deep which should be used instead for a broader compatibility.
UPDATE:
If using Angular-CLI you need to use /deep/ instead of >>> or else it will not work.
ORIGINAL:
After going to Angular2's Github page and doing a random search for "style" I found this question: Angular 2 - innerHTML styling
Which said to use something that was added in 2.0.0-beta.10, the >>> and ::shadow selectors.
(>>>) (and the equivalent/deep/) and ::shadow were added in 2.0.0-beta.10. They are similar to the shadow DOM CSS combinators (which are deprecated) and only work with encapsulation: ViewEncapsulation.Emulated which is the default in Angular2. They probably also work with ViewEncapsulation.None but are then only ignored because they are not necessary. These combinators are only an intermediate solution until more advanced features for cross-component styling is supported.
So simply doing:
:host >>> .child {}
In parent's stylesheet file solved the issue. Please note, as stated in the quote above, this solution is only intermediate until more advanced cross-component styling is supported.
You should not write CSS rules for a child component elements in a parent component, since an Angular component is a self-contained entity which should explicitly declare what is available for the outside world. If child layout changes in the future, your styles for that child component elements scattered across other components' SCSS files could easily break, thus making your styling very fragile. That's what ViewEncapsulation is for in the case of CSS. Otherwise, it would be the same if you could assign values to private fields of some class from any other class in Object Oriented Programming.
Therefore, what you should do is to define a set of classes you could apply to the child host element and implement how the child responds to them.
Technically, it could be done as follows:
// child.component.html:
<span class="label-1"></span>
// child.component.scss:
:host.child-color-black {
.label-1 {
color: black;
}
}
:host.child-color-blue {
.label-1 {
color: blue ;
}
}
// parent.component.html:
<child class="child-color-black"></child>
<child class="child-color-blue"></child>
In other words, you use :host pseudo-selector provided by Angular + set of CSS classes to define possible child styles in child component itself. You then have the ability to trigger those styles from outside by applying pre-defined classes to the <child> host element.
Sadly it appears that the /deep/ selector is deprecated (at least in Chrome)
https://www.chromestatus.com/features/6750456638341120
In short it appears there is (currently) no long term solution other than to somehow get your child component to style things dynamically.
You could pass a style object to your child and have it applied via:
<div [attr.style]="styleobject">
Or if you have a specific style you can use something like:
<div [style.background-color]="colorvar">
More discussion related to this:
https://github.com/angular/angular/issues/6511
Had same issue, so if you're using angular2-cli with scss/sass use '/deep/' instead of '>>>', last selector isn't supported yet (but works great with css).
If you want to be more targeted to the actual child component than you should do the follow. This way, if other child components share the same class name, they won't be affected.
Plunker:
https://plnkr.co/edit/ooBRp3ROk6fbWPuToytO?p=preview
For example:
import {Component, NgModule } from '#angular/core'
import {BrowserModule} from '#angular/platform-browser'
#Component({
selector: 'my-app',
template: `
<div>
<h2>I'm the host parent</h2>
<child-component class="target1"></child-component><br/>
<child-component class="target2"></child-component><br/>
<child-component class="target3"></child-component><br/>
<child-component class="target4"></child-component><br/>
<child-component></child-component><br/>
</div>
`,
styles: [`
/deep/ child-component.target1 .child-box {
color: red !important;
border: 10px solid red !important;
}
/deep/ child-component.target2 .child-box {
color: purple !important;
border: 10px solid purple !important;
}
/deep/ child-component.target3 .child-box {
color: orange !important;
border: 10px solid orange !important;
}
/* this won't work because the target component is spelled incorrectly */
/deep/ xxxxchild-component.target4 .child-box {
color: orange !important;
border: 10px solid orange !important;
}
/* this will affect any component that has a class name called .child-box */
/deep/ .child-box {
color: blue !important;
border: 10px solid blue !important;
}
`]
})
export class App {
}
#Component({
selector: 'child-component',
template: `
<div class="child-box">
Child: This is some text in a box
</div>
`,
styles: [`
.child-box {
color: green;
border: 1px solid green;
}
`]
})
export class ChildComponent {
}
#NgModule({
imports: [ BrowserModule ],
declarations: [ App, ChildComponent ],
bootstrap: [ App ]
})
export class AppModule {}
Hope this helps!
codematrix
Actually there is one more option. Which is rather safe. You can use ViewEncapsulation.None BUT put all your component styles into its tag (aka selector). But anyway always prefer some global style plus encapsulated styles.
Here is modified Denis Rybalka example:
import { Component, ViewEncapsulation } from '#angular/core';
#Component({
selector: 'parent',
styles: [`
parent {
.first {
color:blue;
}
.second {
color:red;
}
}
`],
template: `
<div>
<child class="first">First</child>
<child class="second">Second</child>
</div>`,
encapsulation: ViewEncapsulation.None,
})
export class ParentComponent {
constructor() { }
}
Since /deep/, >>>, and ::ng-deep are all deprecated.
The best approach is to use the following in your child component styling
:host-context(.theme-light) h2 {
background-color: #eef;
}
This will look for the theme-light in any of the ancestors of your child component.
See docs here: https://angular.io/guide/component-styles#host-context
There are a few options to achieve this in Angular:
1) You can use deep css selectors
:host >>> .childrens {
color: red;
}
2) You can also change view encapsulation it's set to Emulated as a default but can be easily changed to Native which uses Shadow DOM native browser implementation, in your case you just need to disable it
For example:`
import { Component, ViewEncapsulation } from '#angular/core';
#Component({
selector: 'parent',
styles: [`
.first {
color:blue;
}
.second {
color:red;
}
`],
template: `
<div>
<child class="first">First</child>
<child class="second">Second</child>
</div>`,
encapsulation: ViewEncapsulation.None,
})
export class ParentComponent {
constructor() {
}
}
I find it a lot cleaner to pass an #INPUT variable if you have access to the child component code:
The idea is that the parent tells the child what its state of appearance should be, and the child decides how to display the state. It's a nice architecture
SCSS Way:
.active {
::ng-deep md-list-item {
background-color: #eee;
}
}
Better way: - use selected variable:
<md-list>
<a
*ngFor="let convo of conversations"
routerLink="/conversations/{{convo.id}}/messages"
#rla="routerLinkActive"
routerLinkActive="active">
<app-conversation
[selected]="rla.isActive"
[convo]="convo"></app-conversation>
</a>
</md-list>
As of today (Angular 9), Angular uses a Shadow DOM to display the components as custom HTML elements. One elegant way to style those custom elements might be using custom CSS variables. Here is a generic example:
class ChildElement extends HTMLElement {
constructor() {
super();
var shadow = this.attachShadow({mode: 'open'});
var wrapper = document.createElement('div');
wrapper.setAttribute('class', 'wrapper');
// Create some CSS to apply to the shadow dom
var style = document.createElement('style');
style.textContent = `
/* Here we define the default value for the variable --background-clr */
:host {
--background-clr: green;
}
.wrapper {
width: 100px;
height: 100px;
background-color: var(--background-clr);
border: 1px solid red;
}
`;
shadow.appendChild(style);
shadow.appendChild(wrapper);
}
}
// Define the new element
customElements.define('child-element', ChildElement);
/* CSS CODE */
/* This element is referred as :host from the point of view of the custom element. Commenting out this CSS will result in the background to be green, as defined in the custom element */
child-element {
--background-clr: yellow;
}
<div>
<child-element></child-element>
</div>
As we can see from the above code, we create a custom element, just like Angular would do for us with every component, and then we override the variable responsible for the background color within the shadow root of the custom element, from the global scope.
In an Angular app, this might be something like:
parent.component.scss
child-element {
--background-clr: yellow;
}
child-element.component.scss
:host {
--background-clr: green;
}
.wrapper {
width: 100px;
height: 100px;
background-color: var(--background-clr);
border: 1px solid red;
}
What I prefer to achieve this is the following:
use #Component to add css class to host element and set encapsulation to none. Then reference that class which was added to the host within the components style.css.scss This will allow us to declare styles which will only affect ourselves and our children within scope of our class. f.e.
#Component({
selector: 'my-component',
templateUrl: './my-component.page.html',
styleUrls: ['./my-component.page.scss'],
host: {
class: 'my-component-class'
},
encapsulation: ViewEncapsulation.None
})
in combination with the following css (my-component.page.scss)
// refer ourselves so we are allowed to overwrite children but not global styles
.my-component-class {
// will effect direct h1 nodes within template and all h1 elements within child components of the
h1 {
color: red;
}
}
// without class "scope" will affect all h1 elements globally
h1 {
color: blue;
}
The quick answer is you shouldn't be doing this, at all. It breaks component encapsulation and undermines the benefit you're getting from self-contained components. Consider passing a prop flag to the child component, it can then decide itself how to render differently or apply different CSS, if necessary.
<parent>
<child [foo]="bar"></child>
</parent>
Angular is deprecating all ways of affecting child styles from parents.
https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep
For assigning an element's class in a child component you can simply use an #Input string in the child's component and use it as an expression inside the template. Here is an example of something we did to change the icon and button type in a shared Bootstrap loading button component, without affecting how it was already used throughout the codebase:
app-loading-button.component.html (child)
<button class="btn {{additionalClasses}}">...</button>
app-loading-button.component.ts
#Input() additionalClasses: string;
parent.html
<app-loading-button additionalClasses="fa fa-download btn-secondary">...</app-loading-button>
i also had this problem and didnt wanted to use deprecated solution
so i ended up with:
in parrent
<dynamic-table
ContainerCustomStyle='width: 400px;'
>
</dynamic-Table>
child component
#Input() ContainerCustomStyle: string;
in child in html div
<div class="container mat-elevation-z8"
[style]='GetStyle(ContainerCustomStyle)' >
and in code
constructor(private sanitizer: DomSanitizer) { }
GetStyle(c) {
if (isNullOrUndefined(c)) { return null; }
return this.sanitizer.bypassSecurityTrustStyle(c);
}
works like expected and should not be deprecated ;)
As the internet updates I've come across a solution.
First some caveats.
Still don't do it. To clarify, I wouldn't plan on child components allowing you to style them. SOC. If you as the component designer want to allow this then all the more power to you.
If your child doesn't live in the shadow dom then this won't work for you.
If you have to support a browser that can't have a shadow dom then this also won't work for you.
First, mark your child component's encapsulation as shadow so it renders in the actual shadow dom. Second, add the part attribute to the element you wish to allow the parent to style. In your parent's component stylesheet you can use the ::part() method to access
This is a solution with just vanilla css, nothing fancy, you don't even need !important. I assume you can't modify the child, otherwise the answer is even more simple, I put that answer at the end just in case.
Overriding a child's CSS is sometimes needed when using a pre-made component from a library, and the devs have not provided any class input variables. ::ng-deep is deprecated and encapsulation: ViewEncapsulation.None turns all of your component's CSS global. So here is a simple solution that uses neither of those.
The fact is, we do need a global style in order for the CSS to reach the child. So, we can just put the style in styles.css or we can create a new CSS file and add it to the styles array in angular.json. The only issue is that we need a specific selector so as not to target other elements. That's a pretty easy solution - just add a unique class name to the html, I recommend using the parent component's name in the class name to ensure it is unique.
Parent Component
<child class="child-in-parent-component"></child>
Let's pretend we want to change the background-color of all the buttons within the child, we do need to achieve the correct specificity to make sure our styles take precedence. We can do this with !important next to all our properties, but a better way is to just repeat the class name until our selector is specific enough, may take a few tries. That way, someone else can override this css again if necessary.
Global Styles File
.child-in-parent-component.child-in-parent-component.child-in-parent-component
button {
background-color: red;
}
or quick and dirty with !important (not recommended)
.child-in-parent-component button {
background-color: red !important;
}
If the child component can be modified
Simply add an input variable to the component and make use of Angular's ngStyle directive. You can add multiple variables to style multiple areas of your component.
Child Component
type klass = { [prop: string]: any } | null;
#Component({...})
export class ChildComponent {
#Input() containerClass: klass = null;
#Input() pClass: klass = null;
...
}
<div [ngStyle]="containerClass">
<p [ngStyle]="pClass">What color will I be?</p>
</div>
Parent Component
<child
[containerClass]="{ padding: '20px', 'background-color': 'black' }"
[pClass]="{ color: 'red' }"
>
</child>
This is the intended way to create a component with a dynamic style. Many pre-made components will have a similar input variable.
this has worked for me
in the parent component:
<child-component [styles]="{width: '160px', borderRadius: '16px'}" >
</child-component>
I propose an example to make it more clear, since angular.io/guide/component-styles states:
The shadow-piercing descendant combinator is deprecated and support is being removed from major browsers and tools. As such we plan to drop support in Angular (for all 3 of /deep/, >>> and ::ng-deep). Until then ::ng-deep should be preferred for a broader compatibility with the tools.
On app.component.scss, import your *.scss if needed. _colors.scss has some common color values:
$button_ripple_red: #A41E34;
$button_ripple_white_text: #FFF;
Apply a rule to all components
All the buttons having btn-red class will be styled.
#import `./theme/sass/_colors`;
// red background and white text
:host /deep/ button.red-btn {
color: $button_ripple_white_text;
background: $button_ripple_red;
}
Apply a rule to a single component
All the buttons having btn-red class on app-login component will be styled.
#import `./theme/sass/_colors`;
/deep/ app-login button.red-btn {
color: $button_ripple_white_text;
background: $button_ripple_red;
}
I have solved it outside Angular. I have defined a shared scss that I'm importing to my children.
shared.scss
%cell {
color: #333333;
background: #eee;
font-size: 13px;
font-weight: 600;
}
child.scss
#import 'styles.scss';
.cell {
#extend %cell;
}
My proposed approach is a way how to solve the problem the OP has asked about. As mentioned at multiple occasions, ::ng-deep, :ng-host will get depreciated and disabling encapsulation is just too much of a code leakage, in my view.
let 'parent' be the class-name of parent and 'child' be the class-name of child
.parent .child{
//css definition for child inside parent components
}
you can use this format to define CSS format to 'child' component inside the 'parent'

Angular 2: How to style host element of the component?

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.
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.
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{ ... }
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
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';
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
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

Resources