svelte icon indicating copy to clipboard operation
svelte copied to clipboard

CSS Component Selector

Open DeepDoge opened this issue 2 years ago • 2 comments

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

DeepDoge avatar Jul 18 '22 06:07 DeepDoge

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.

DeepDoge avatar Jul 18 '22 07:07 DeepDoge

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.

jhwz avatar Jul 23 '22 02:07 jhwz

Related to:

  • #6972
  • #7125 ?
  • sveltejs/rfcs#63
  • sveltejs/rfcs#66
  • #6422
  • #2870 ?
  • #5804
  • #7776 ?

MacFJA avatar Aug 13 '22 21:08 MacFJA

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.

DeepDoge avatar Aug 13 '22 23:08 DeepDoge

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! 😄

valterkraemer avatar Oct 13 '22 11:10 valterkraemer