svelte
svelte copied to clipboard
CSS Component Selector
Describe the problem
It's a common thing using components to have personalized HTML elements.
For example <img />
element, i can make a <Image>
component that uses <picture>
by default or loading="lazy"
attribute. So it's easier to re-use or change.
The problem is its still common to add custom styles to image element, like background-color
object-fit
and many other stuff, like aspect-ratio
, width
etc.
Svelte components doesn't allow that unless you make somehow :global()
hacks. Which doesn't give warnings when invalid and looks hacky. And when you not try to use :global()
it becomes even more hacky and makes you use a lot of boilerplate code.
Describe the proposed solution
A CSS component selector to select all of the root elements in the component.
Example: foo.svelte
<div>
<img />
<div/>
<a />
bar.svelte
<div>
<Foo />
</div>
<Foo />
<style>
div > $Foo { /* Selects `div` and `a` element in the `Foo` component, because they are in the root */
...
}
<style />
syntax can change.
Alternatives considered
An option to bind everything(attributes(class), events...) in a root element in the component.
Example: foo.svelte
<div bind:$$root>
<img />
<div />
<div />
bar.svelte
<Foo class="thing" on:click={() => alert()}>
<style>
.thing { /* this would only select the first `div` element in the `Foo` component
...
}
<style />
if none of these are applicable at least having a way to bind/pass/inherit all of the events would be cool.
Importance
would make my life easier
I was thinking and, or maybe something like:
div > :$Foo {
...
}
div > :$Foo(div) {
...
}
Also can be used like
div > :$Foo(div > img) {
...
}
which lets you use the selectors inside the component's scope
which is similar to :global()
but more specific and IDE knows more it, so it can give warnings or auto suggestions.
Having a way to target components with CSS would be awesome.
There must be existing proposals or discussions that have touched on this but for me personally this would be a great quality of life improvement, saves having to make classes and pass those down.
As a start, you could have it only work on components that have a single, top-level HTML element in them (so in your case the <a />
in foo.svelte would be disallowed). Potentially later you could introduce a syntax to target elements in that child component as you've shown.
Related to:
- #6972
- #7125 ?
- sveltejs/rfcs#63
- sveltejs/rfcs#66
- #6422
- #2870 ?
- #5804
- #7776 ?
Having a way to target components with CSS would be awesome.
There must be existing proposals or discussions that have touched on this but for me personally this would be a great quality of life improvement, saves having to make classes and pass those down.
As a start, you could have it only work on components that have a single, top-level HTML element in them (so in your case the
<a />
in foo.svelte would be disallowed). Potentially later you could introduce a syntax to target elements in that child component as you've shown.
tbh :$Foo
would selects everything inside the component and div > :$Foo
selects only the top ones.
:$Foo
really stands for the component's component css id. :$Foo
would be equal to :$Foo(*)
so if you say :$Foo(img)
it selects every image inside every Foo component inside the current component
so in theory to select the first top element you can do tricks like * > :$Foo
or * > :$Foo(*)
so as i said similar to :global()
and it just gives more info to IDE and more control over your selection.
I proposed a different Component selector approach in https://github.com/sveltejs/svelte/issues/6972#issuecomment-1277463898, and even created a POC svelte-preprocessor that allows you to use the approach today! 😄