What is the different between :host ,:host() ,:host-context selectors
:host
Is syntax for styling the host component.
:host(.element)
Is an experimental CSS pseudo-class function that selects the shadow host of the shadow DOM containing the CSS it is used inside
(Reference)
:host-context
Is syntax for styling a specific class anywhere outside the current element. The class must already be applied to an element outside the scope of the current element.
More in-depth info on the context of Angular applications can be found in this blog post.
What is the use case of :host-context selector in angular
This answer explains the difference between host
and host-context
. Here is an example of host-context
usage. Suppose you have a component that wraps an input and this input can be used inside two different components - table and dropdown. When inside a dropdown it should occupy 50% of the width, when in table - 100%. Now if you have these two components selectors defined like this:
<my-dropdown>
<my-table>
Then the styles for the input component can be defined like this:
:host-context(my-dropdown) input { width: 50% }
:host-context(my-table) input { width: 100% }
Scope of :host-context(.class) selector
:host-contexts checks class on host element same as :host and then ancestors as you know. So your tests works fine. Please don't forget that css property color is inherited to children.
Understanding the basics of :host-context
My understanding is that :host-context
is like :host
except you can pass it a selector, and it will only match if the shadow host matches that selector in the light DOM. So lets say you have a custom element my-element. You want to style this div background color: red, but only if the my-element
is in an H1, because it shouldn't appear in an H1 and the red is a clear sign to the dev that they made a mistake.
You can do this:
:host-context(h1) { background-color: red }
And the red background will only show up if my-element is a descendent of an h1.
<h1>
<my-element></my-element> <!-- red! warning! -->
</h1>
<div>
<my-element></my-element> <!-- no red, a-ok -->
</div>
Cannot Understand the Use of :host in components in Angular2
What i have understood of host is that if i have a child component
inside a parent component and we want to style a child component from
the parent component we can use :host . and :host-context for
vice-versa
No, this is not what it used for.
:host
selector comes from shadow DOM spec.
...This scoped subtree is called a shadow tree. The element it's
attached to is its shadow host.
In angular world, a component's template is a shadow tree. The component's element is a shadow host. So when you're defining styles for :host
selector, the styles are applied to the component's element.
:host
In your example, if you defined styles in my-app
component, the styles will be applied to <my-app>
DOM element. This particular configuration:
:host(.mine){
color:red;
}
Will be applied to the host element that has .mine
class:
<my-app class="active">
If you defined styles in app-ngrx
component, the styles will be applied to <app-ngrx>
DOM element, NOT <my-app>
. This particular configuration:
:host(.mine){
color:red;
}
Will be applied to the host element that has .mine
class:
<app-ngrx class="active">
:host-context
Now, :host-context
is also applied to the host element, but the function (parenthesis) takes a selector that is checked not against the host element itself, but against all ancestors up to document root. If such element is found, the styles are applied.
For example, this selector
:host(.mine){
color:red;
}
matches such structure:
<my-app class="mine">
whereas, this selector:
:host-context(.mine){
color:red;
}
matches this structure:
<div class="mine">
...
<my-app>
This is useful, if you want to apply styles to components view (shadow root) conditionally. This makes h2
always bold:
h2 {
font-weight: bold;
}
whereas this
:host-context(.make-inner-components-bold) h2 {
font-weight: bold;
}
makes them bold only if your component is inside an element with class .make-inner-components-bold
.
Why does the :host selector only work in chrome with platform.js?
Question is a bit old, but putting this answer here in case you didn't figure it out yet.
Shadom DOM polyfill doesn't attempt style encapsulation or fixing shadom dom related selectors in non-supported browsers.
This is the reason that other than :host/:content selectors and :host()/:host-context() pseudo-classes not working, you'll see style written inside shadow dom leaking on to the whole page.
The way you can make :host selectors work(?), is by rewriting css rules and replacing :host with tag name of host element.
If you have an x-element custom-element then something like this:
:host { opacity: 0.4; transition: opacity 420ms ease-in-out;}:host(:hover) { opacity: 1;}:host(:active) { position: relative; top: 3px; left: 3px;}/*Convert it to*/
x-element { opacity: 0.4; transition: opacity 420ms ease-in-out;}x-element:hover { opacity: 1;}x-element:active { position: relative; top: 3px; left: 3px;}
How to use :host-context selector in an ngClass condition?
In angular you should not make any logical decisions in the code based on the html content properties such as classes or attributes, but vice versa - you should render classes and attributes in html based on data bindings. That's the main idea of angular - rendering view based on data bindings. Component's code should not really care too much about view structure.
So, in this case if your class should be based on some external information you need to @Import() that data through data bindings into your component and then use component properties in the ngClass directive. Yes, it moves logic into the component instead of html/css, but that's where it's supposed to be anyway: in the model/controller code, not in the view markup. Also, this way it will be much more convenient to test such a component.
Using :host-context() with an adjacent sibling selector
:host()
and :host-context()
only accept a compound selector as their argument, and not a complex selector.
x-foo[active] + x-foo
is a complex selector that contains two compound selectors, x-foo[active]
and x-foo
, separated by the adjacent sibling combinator. :host()
and :host-context()
can accept either compound selector, but not any combinators.
Unfortunately, because the shadow host's siblings do not exist in the shadow context, you won't be able to write something like x-foo[active] + :host
. As a consequence, I don't think you will be able to accomplish what you're looking to do in a shadow context. (In the light context, of course, you can just write x-foo[active] + x-foo
, but that defeats the purpose of prepackaging CSS into a web component.)
It's not clear to me why :host()
and :host-context()
weren't specced to allow complex selectors in the first place, since if they did, what you have would have just worked.
Related Topics
Is Decimal Precision When Specifying a Font-Size Respected by All Browsers
CSS Modules - Referencing Classes from Other Modules
Can the :Before and :After Pseudo-Elements Inherit Height from the Parent Element
Css/Webkit: Background Images for Table Row
Cross-Browser 'Cursor:Pointer'
CSS Equivalent to Photoshop's Justify-All
Getting the Right Font-Size on Every Mobile Device
How to Change Height of Ui-Grid Row
Best Practices - Only Download CSS You Need, or Use a Minification Process
Is the Hash Necessary in Svg Font-Face Declarations
Iframe Horizontal Scrolling Not Rendering on iOS
How to Use CSS Text-Overflow on Text That's Wrapping
CSS 3 or Svg Wave in a Background
Clip-Path Does Not Work with Chrome