Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS Component Selector #7694

Open
DeepDoge opened this issue Jul 18, 2022 · 5 comments
Open

CSS Component Selector #7694

DeepDoge opened this issue Jul 18, 2022 · 5 comments
Labels
css Stuff related to Svelte's built-in CSS handling feature request

Comments

@DeepDoge
Copy link

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
Copy link
Author

DeepDoge commented Jul 18, 2022

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.

@jhwz
Copy link

jhwz commented Jul 23, 2022

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.

@baseballyama baseballyama added feature request css Stuff related to Svelte's built-in CSS handling labels Aug 11, 2022
@DeepDoge
Copy link
Author

DeepDoge commented Aug 13, 2022

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.

@valterkraemer
Copy link
Contributor

I proposed a different Component selector approach in #6972 (comment), and even created a POC svelte-preprocessor that allows you to use the approach today! 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css Stuff related to Svelte's built-in CSS handling feature request
Projects
None yet
Development

No branches or pull requests

5 participants