Often when I'm writing scoped CSS for my components I need to put a class on the root element so that I can style it. For example:
<template>
<div class="foo-root">Hello World</div>
</template>
<style scoped>
.foo-root {
color: red
}
</style>
CSS already supports a :root selector which means the "root HTML element of the document" (i.e. usually the <html> element).
As far as I know it's never possible for a component to be the root <html> element of the document. So this :root selector effectively does nothing inside scoped CSS.
Therefore, why not repurpose it to mean the component's root element? We could then re-write the example above without needing to add a specific class:
<template>
<div>Hello, World</div>
<template>
<style scoped>
:root {
color: red;
}
</style>
Admittedly a small idea, but one that I think would save a fair bit of typing (and inventing class names)!
+1024 for this one!
I had this in mind as well, good idea.
...come to think of it, the solution can be as simple as:
<template>
<div>
// other markup
</div>
</template>
<style scoped>
div:first-child { ... }
</div>
Maybe this is what a lot of people already do?
:host seems like a better alternative to the :root I originally proposed!
Or to think of it... how about $el?
If that's valid CSS syntax - would be really natural to use given $el is already how we access the component's element inside <script>...
...come to think of it, the solution can be as simple as:
<template> <div> // other markup </div> </template> <style scoped> div:first-child { ... } </div>Maybe this is what a lot of people already do?
I just tried it, and it doesn't work.
Besides, this assumes you have a knowledge of the first element being a div, meaning this could not applied to this:
<template>
<a v-if="isLink" href="...">{{ text }}</a>
<span v-else>{{ text }}</span>
</template>
:host or :root appear like more generic solutions.
@davidhewitt In my opinion:
:host looks semantically like a new concept, it sounds like "we couldn't use :root so we had to find another term".
$el doesn't look CSS at all.
As you pointed out, :root means "root HTML element of the document" (i.e. usually the element) - so it totally makes sense in a scoped context.
@jfbrennan :root doesn't _necessarily_ mean <html>, according to MDN:
The :root CSS pseudo-class matches the root element of a tree representing the document.
In HTML, :root represents the element and is identical to the selector html, except that its specificity is higher.
Perfectly fine in our case IMHO.
it sounds like "we couldn't use :root so we had to find another term".
:host is a normal CSS pseudo-class though, and it is absolutely appropriate here since Vue’s component syntax is loosely modeled after the [Web Component] spec.
$eldoesn't look CSS at all.
True.
@jfbrennan
:rootdoesn't _necessarily_ mean<html>, according to MDN:The :root CSS pseudo-class matches the root element of a tree representing the document.
In HTML, :root represents the element and is identical to the selector html, except that its specificity is higher.Perfectly fine in our case IMHO.
What about this sounds "Perfectly fine"? 😅 The definition you yourself have quoted states:
_"In HTML, :root represents the element and is identical to the selector html"_
Yes, :root doesn't _necessarily_ mean html because it can be used in SVG documents, too – but this is quite clear-cut, usage in HTML → html selector → impractical for the proposed usage as Vue component root.
FWIW, if anyone's feeling passionate about pushing this forward and has a spare evening, it would probably be a great time to write a Vue 3 RFC on this feature. Especially inspiration could be drawn from https://github.com/vuejs/rfcs/pull/119
(I'm too busy on other projects at the moment or I might have considered writing the RFC myself)
:host is a normal CSS pseudo-class though, and it is absolutely appropriate here since Vue’s component syntax is loosely modeled after the [Web Component] spec.
My bad, I should have googled more 😅I definitely thought it was an invention of some framework to do the trick we wanted to copy/paste. I go back on my word then, :host sounds better indeed 🙂
Is this issue stalled?
I would like to upvote the:host suggestion. Why? because it is necessary to select the root element of a component without using an id or class attribute. I think it is important for re-useable components.
Example structure
<template>
<div>
<div>Hello World</div>
</div>
</template>
Setting a style for the outer div cannot be accomplished with div:frist-child (as suggested in this thread) because it would also match the inner div.
Using a CSS class with scoped context leads to a HTML document which is not nice when the component is used
<template>
<div class="foo">
<div>Hello World</div>
</div>
</template>
<style scoped>
.foo {
color: red
}
</style>
When someone now uses my component
<Foo></Foo>
and adds a CSS class called "foo"
<Foo class="foo"></Foo>
the generated HTML looks like
<div class="foo foo" data-v-654321 data-v-123456>
<div>Hello World</div>
</div>
I just want to use styles inside my component for my root element without weird CSS usage.
So I would love to use
<template>
<div>
<div>Hello World</div>
</div>
</template>
<style scoped>
:host {
color: red
}
</style>
Which then should lead to
<div class="foo" data-v-654321 data-v-123456>
<div>Hello World</div>
</div>
when used as described above.
Was RFC created for this?
Most helpful comment
+1024 for this one!