Skip to content

Css variable declaration shorthand #16071

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

Open
JonathonRP opened this issue Jun 3, 2025 · 15 comments
Open

Css variable declaration shorthand #16071

JonathonRP opened this issue Jun 3, 2025 · 15 comments
Labels
css Stuff related to Svelte's built-in CSS handling

Comments

@JonathonRP
Copy link

JonathonRP commented Jun 3, 2025

Describe the problem

Js variables ability to use in css best option is a style directive, and svelte 5 moving away from directive uses it would not be easily remembered to use which makes it harder to use js in css.

Describe the proposed solution

To be able to use <style --x={x}> to declare css variable with shorthand to make using js variable in css as css variable easier and nicer.

(also see #16071 (comment))

Importance

would make my life easier

@paoloricciuti
Copy link
Member

Oh yesterday I wanted to comment on bsky but it errored out.

One thing I don't like about this is that then we would have two ways of doing the same thing and that we would need to wrap everything in an element with display contents especially since doing this is not a huge advantage over style:--var.

I was also wondering: since we don't have props on the style tag we could technically do this

<style {x}>
...
</style>

Which will give you the ability to use the shorthand which you basically can't do now.

I don't know I'm very torn.

@JonathonRP
Copy link
Author

This has one advantage over style:--var and that style:--var only works on element. And my use case I actually want to pass variable values from a wrapping element that doesn't have direct access to child element but the css can target it...

@paoloricciuti
Copy link
Member

This has one advantage over style:--var and that style:--var only works on element. And my use case I actually want to pass variable values from a wrapping element that doesn't have direct access to child element but the css can target it...

Can you show me an example?

@JonathonRP
Copy link
Author

I like your suggestion and also there are two ways to do a lot of things in svelte right now, legacy (children) and not (class)

@JonathonRP
Copy link
Author

@paoloricciuti
Copy link
Member

Yeah but you can just wrap it with an element yourself:

<css-props style:--var={var} style:display="contents">
// Snippet
</css-props>

Which is the same thing svelte would do

@JonathonRP
Copy link
Author

JonathonRP commented Jun 3, 2025

That's true but that's a lot to know and svelte is also about the vibes...

I like the

<style {x}>
...
</style>

@Thiagolino8
Copy link

Instead of messing with the style tag, one option would be to make props that start with -- be interpreted as css variables

<div --var={var}></div>

So instead of wrapping a component with an extra div as is currently done, you could do as with attachments and simply use the spread on the element you want to use the variable in, or even define one by one

// App.svelte
<Comp --var={var} />

// Comp.svelte
<script>
	let props = $props()
</script>

<div {...props}></div>
// or
<div --var={props['--var']}></div>

Unfortunately, this would be a breaking change.

@dummdidumm
Copy link
Member

I don't fully understand this request TBH. Is this a feature request to do the same thing a bit differently in fear of style: going away at some point and/or not being of the same syntax? Or is it requesting something else? Can someone give more context (potentially linking to that bsky thread)?

@dummdidumm dummdidumm added the awaiting submitter needs a reproduction, or clarification label Jun 3, 2025
@paoloricciuti
Copy link
Member

@dummdidumm here's the bsky link ...I honestly agree that while it might look interesting is probably to niche of a feature to add considering there's already a way of doing it which is also very simple and more "clear" about what's going on

@dummdidumm
Copy link
Member

Ok so this is about supporting

<script>
  let color = 'red';
</script>

<button onclick={() => color = 'blue'}>change color</button>

<style --color={color}>
  button {
    color: var(--color);
  }
</style>

@dummdidumm dummdidumm added css Stuff related to Svelte's built-in CSS handling and removed awaiting submitter needs a reproduction, or clarification labels Jun 3, 2025
@paoloricciuti
Copy link
Member

Correct

@Ocean-OS
Copy link
Contributor

Ocean-OS commented Jun 3, 2025

Is there even a performant way to do that? Unless we manipulate a <style> element's innerHTML in a render effect or wrap all components in divs or spans, I don't really see a solution to this. We could try to do some analysis on each declaration and see which ones rely on which elements to do something like this...

<style --color={color} >
    button {
        color: var(--color); 
    } 
</style>
<button></button>
//becomes
$.template_effect(() => {
    button.style.color = $.get(color); 
}) 

But that seems overly complex (as we'd have to incorporate the logic for every selector and pseudo selector into the compiler, and transform the css property logic (eg calc()) to JS code) for little gain.

@JonathonRP
Copy link
Author

Astro has achieved it in their astro components.
1 idea I think it could be enough is the variables are root variables with or without scope

@paoloricciuti
Copy link
Member

@Ocean-OS if all the top level are elements we just add the variables to all the elements, otherwise we wrap the whole object with the svelte-css-props element with display contents.

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