sveltejs / rfcs

RFCs for changes to Svelte
274 stars 81 forks source link

JS in CSS #51

Closed bluwy closed 3 years ago

bluwy commented 3 years ago

Rendered

antony commented 3 years ago

I'd be tempted to say that the backtick character doesn't appear in CSS so this might be a better syntax than js.

Overall I think this is a nice idea, but I feel like it might be hellish given all the css preprocessors people are using.

bluwy commented 3 years ago

@antony Interesting, through some digging I found that backticks were also once used by Less for inline javascript, so there was an existing convention! (Though deprecated by Less)

I've updated by my repo to test out multiple preprocessors and the backtick syntax. Result:

  1. js() works for all preprocessors. The vscode extensions I tried for syntax highlighting doesn't nag much too.
  2. Backtick syntax failed for all preprocessors and even Svelte's css parser. The vscode extensions nag a bit too.

Looks like backticks doesn't get enough love from the preprocessor ecosystem.

Update: js() works in less too, but it needs to be escaped if they're quotes within the parentheses, e.g. width: ~"js(num + 'px')";.

pngwn commented 3 years ago

What does this give us that css variables don't?

I don't think the 'difficult to learn' criticism of css variables is valid. It is a standard and is no less esoteric then this proposal. Aligning to existing web standards where possible has always been a design goal.

This would add a huge amount of complexity to the css handling and would be a significant feature.

bluwy commented 3 years ago

@pngwn Perhaps the biggest benefit this gives that CSS variables don't is that CSS variables can be scoped by Svelte, similar to how classes work. Besides that, it's purely subjective whether the syntactic sugar is actually worth it.

I'm currently comparing this to style properties as it plays at the same "syntactic sugar" feature level, that both can be done with pure CSS variables manually.

Regarding web standards, I chose js() as it's the least web-breaking feature and plays as the same area in calc() and var(), so most preprocessors would've took into account of this function syntax. There's also a CSS Houdini draft that further expands on custom CSS functions, so there could be a future where this would be a standard syntax.

But if the goal is to stick proper laid-out web standards, then I'm fine if we wait longer for the CSS ecosystem to progress, but at the same time it'll be interesting for Svelte to take the first leap.

pngwn commented 3 years ago

The issue there is that we don't want endless sugar, we already have the css properties thing we don't want to keep adding different kinds of sugar to do the same thing.

We have a pretty clear preference to use the simplest, most standardised approach where possible.

bluwy commented 3 years ago

I agree that having too much sugar isn't great, but however I don't think the style properties feature is doing the same thing as this, as highlighted in the technical background section.

Furthermore, in a bigger picture of JS in CSS, I'd like to see CSS variables as the implementation detail only. So would the consensus be that JS in CSS would not be implemented/considered in the future?

Nonetheless, I'm hoping to have a final answer for this as it's a topic that comes around from time to time.

TehShrike commented 3 years ago

I've gotten by in a lot of cases by just putting the dynamic CSS on the elements e.g. <div style="width: {num}px">Hello</div>

catielanier commented 3 years ago

I've gotten by in a lot of cases by just putting the dynamic CSS on the elements e.g. <div style="width: {num}px">Hello</div>

While that's fine, it's not necessarily the most dry if you're going to be repeating the same style in multiple places, especially you have more than one rule that might need some dynamic rules in the same element. Would be nice to frame this off a class and do the dynamic stuff in CSS with that class and apply it all with one class definition.

bluwy commented 3 years ago

Just realized Vue had this feature for a while now in this RFC and have recently be merged into Vue 3.2. It's using v-bind() instead of js(), with great positive feedback there.

Theo-Steiner commented 3 years ago

This came up in the discord today because someone shared a link of vue's implementation of this and people (at least I) got very excited about the idea of having this in svelte as well. I was wondering rather than introducing a new syntax of js() to svelte's css, why not allow for this syntactically by using the already existing var() with curly braces like in the html-like part of svelte?

<script>
let color = 'hotpink'
</script>
<h1>Pretty in pink</h1>
<style>
h1 {
  background-color: var({color});
}
</style>

if this desugars to something like this

<script>
let color = 'hotpink'
</script>
<h1 style="--svelte-hash-h1: {color};">Pretty in pink</h1>
<style>
h1 {
  background-color: var(--svelte-hash-h1);
}
</style>

the var({ javascript }) syntax would be very intuitive

bluwy commented 3 years ago

@Theo-Steiner The issue with that syntax, or any other curly braces syntax, is that they don't work well with IDE extensions. I've tested them in VSCode with this repo for postcss, sass, and even normal css, they all currently report parsing errors, which the Svelte vscode extension can't handle (?) as the syntax highlighting are all done by external vscode extensions.

Using js() would be the least destructive way, similar to v-bind().

Mlocik97 commented 3 years ago

with https://github.com/sveltejs/rfcs/pull/42 I don't think, we will need this RFC at all, and I think, this will add more complexity and unexpected behaviours and other disadvantages than advantages. CSS can be dynamic only in values, that are already covered by CSS variables, so I don't see any reason to have this. But I actually like idea of https://github.com/sveltejs/rfcs/pull/51#issuecomment-895848289

bluwy commented 3 years ago

@Mlocik97 I guess so, looks like #42 had some discussion related to this feature too. Though I don't think it completely overlaps with this usecase-wise (e.g. https://github.com/sveltejs/rfcs/pull/51#issuecomment-868579809) and feature-wise (e.g. hashed css vars). But I'd agree if that RFC got merged, it would be really weird to have this merged as well since we would have too many ways of doing similar things.

But I actually like idea of https://github.com/sveltejs/rfcs/pull/51#issuecomment-895848289

As explained in the comment above, unless we embrace breaking every tooling out there, it won't be a viable option. {} is already reserved in css and I don't think we should bend it.

Mlocik97 commented 3 years ago

 {} is already reserved in css and I don't think we should bend it.

I don't think this is problem at all. And it's not really reserved.

bluwy commented 3 years ago

I've tried that before and it is a problem. If you insist, you can try implementing that variant based on https://github.com/bluwy/svelte-js-in-css then.

bluwy commented 3 years ago

Closing this as half of the votes are not in favour of this feature.

windyclory commented 2 years ago

@bluwy Good job, I liked it. I like this syntax more:

width: {width}px