Reputation: 38457
With a normal React/Vue component I normally create a custom CSS class and use that to style the component like so:
<div class="foo">
...
</div>
.foo {
}
With web components, there is the additional option to use the :host
psuedo-selector. I understand that it can be used to apply styles to the web component HTML element itself.
<div class="foo">
...
</div>
.foo {
}
:host {
}
When should I use :host
versus a custom CSS class like .foo
?
Upvotes: 1
Views: 2368
Reputation: 21183
An important part you do not mention, is that React (and other Frameworks), in the build step, rewrites all your classNames, to create "unique" class names.
React does not scope CSS like shadowDOM does.
Below answer is for a Web Component with shadowDOM;
Note that shadowDOM can be attached to regular DOM Elements as well. Same answer applies.
:host
refers to your ... host...Web Component DOM element: <my-element>
Bluntly said, you could compare it to html,head,body
in global CSS, it is the container element
The CSS inside does not (have to) know the element name my-element
classes (or any CSS selector you know) style Web Component content
OR, if you are not using shadowDOM, they style your whole document,
because unlike Frameworks, classNames are not changed, to be "unique", in the Build step.
And do learn <slot>
behaviour:
::slotted CSS selector for nested children in shadowDOM slot
<style>
.foo {
border:1px solid red; /* CSS not applied to elements in shadowDOM */
font: 30px Arial; /* for UX consistancy, font styles DO style shadowDOM */
}
</style>
<span class="foo">
<my-element>Hello</my-element>
Web Components
<my-element pink>World</my-element>
</span>
<template id="MY-ELEMENT">
<style>
:host {
display:inline-block;
background:lightgreen;
}
:host([pink]) { background:hotpink }
.foo { font-weight:bold; /* does NOT style anything outside this shadowDOM */ }
</style>
<slot class="foo"></slot>
</template>
<script>
customElements.define('my-element', class extends HTMLElement {
constructor() {
super().attachShadow({mode: 'open'})
.append(document.getElementById(this.nodeName).content.cloneNode(true));
}
});
</script>
Upvotes: 3