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

Scope css styles to a different Svelte component #8635

Open
robertadamsonsmith opened this issue May 25, 2023 · 3 comments
Open

Scope css styles to a different Svelte component #8635

robertadamsonsmith opened this issue May 25, 2023 · 3 comments
Labels
css Stuff related to Svelte's built-in CSS handling
Milestone

Comments

@robertadamsonsmith
Copy link

Describe the problem

The existing ways of scoping css styles to a child component don't feel right. Either they require customisable components to expose a lot of properties for styling purposes, which does not feel right, or for :global() to be used in a way that can cause styles that are designed to target a child component to leak into other descendant components.

Describe the proposed solution

Just as :global() is used to strip the prefix from selectors, we could allow the name of a component such as :MyButton() to be used to add the appropriate prefix to a selector, so that it can target elements in a descendant component. It would look like this:

<script>
	import MyButton from "./MyButton.svelte"
</script>

<div>
	<MyButton>Click Me!</MyButton>
</div>

<style>
	div :MyButton(button){
		background-color:red;
	}
</style>

I think that a containing element would usually be necessary, to avoid the style from being applied 'globally' to all instances of MyButton (much like how :global() is generally used).

Alternatives considered

The usual approach is to use :global(), but that can cause a descendant component to be accidentally targeted as well, such as illustrated here, since the selector in the :global() section cannot be restricted to just the component that we really want to style:

<script>
	import MySheet from "./MySheet.svelte"
	import MySection from "./MySection.svelte"
</script>

<div>
	<MySheet>
		<MySection>First Section</MySection>
		<MySection>Second Section</MySection>
	</MySheet>
</div>

<style>
	div :global(div){
		background-color:red;
	}
</style>

A child selector can stop the style leaking beyond the child (i.e. div > :global(div)), but then it makes the relationship more fragile. Another way to stop the style leaking is to add uncommon class names to elements so that they can be more precisely targeted from ancestors (i.e. div > :global(.mysheet-div)), but that feels very verbose.

Another approach is to expose styles through attributes, but that requires a lot of repetitive work, and prevents styling from being expressed through css, and so doesn't feel like the correct approach.

Importance

would make my life easier

@karimfromjordan
Copy link

Related issue: #4661

@Tyrenn
Copy link

Tyrenn commented Jul 11, 2023

Kinda related to #8538

@langsys
Copy link

langsys commented Jan 6, 2024

I love this solution, very svelteish, keeps things clean, and dodges the ugly use of :global

@Rich-Harris Rich-Harris added the css Stuff related to Svelte's built-in CSS handling label Apr 3, 2024
@Rich-Harris Rich-Harris added this to the 5.0 milestone Apr 3, 2024
@trueadm trueadm modified the milestones: 5.0, 5.x Jun 5, 2024
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
Projects
None yet
Development

No branches or pull requests

5 participants