-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Description
Describe the problem
In my svelte builds. I consistency come up against the same problems with writing CSS for which I have found work arounds, but am always left feeling like there could be a better implementation to make CSS a first class citizen in svelte and bring features no other framework can provide without a compiler.
It seems to me that there is room for improvement by way of consistency, syntax and features that would take very little work to implement and create almost no technical debt.
Outlined below are all several ways currently to add css and how I see them them being improved.
1. Scoped styles
This is the default. Simply adding a style element to the file creates scoped css. I see no problem with this.
2. Global, using the :global() selector
I've never liked this method. This selector feels like neither svelte nor CSS. Its anatomy is that of a css pseudo-selector, but there are no pseudo selectors that "float" like this, unattached to an element selector. It's also very likely that one would want several lines of css to be global and this provides no solution. I implemented nesting via post css to try to get the desired effect, e.g.
:global {
&(body){
background: blue;
}
&(header){
background: black;
}
}
This works, but is unnecessarily clunky.
The Solution?
I'd recommend a very simple change here. Keep :global() for the sake of backwards compatibility and add a "global" attribute that can be used on style block very similar to the "scoped" attr you can add in Vue. So a new bit of styling would look something like this:
<style>
section{
max-width: 80rem;
}
</style>
<style global>
header{
background: black;
}
</style>
3. Global and unmounted
Currently, if you add css using :global(), when navigating away from a page, that css will persist in the app. For example, if I want the header to be a different color on a specific page, I could use the :global() selector inside the page css to affect the header, but when I navigate to another page, that css will still be affecting the header. I could move the header color to a svelte store and use js to change the color, but it's an unnecessary burden. There is a simple workaround within svelte that is kind of a hack--that is to include this css in a style block inside of the component markup, not at the top level. There's nothing wrong with this except readability. It's not officially mentioned in the svelte docs. I always include a comment when I do this because without a comment, it will leave the next dev wondering... why? I'm recommending again adding a flag to the style block that could achieve this effect, have it's purpose be immediately clear, and be part of the official documentation. Something like:
<style global temp>
header{
background: black;
}
</style>
4. Via JS
When the class directive isn't quite right for the job, we can use JS to add styles to an element. I'd much rather write css in css than in JS, so I often use JS to set CSS variables on my elements and then use CSS to do the actual styling. This usually works and I think is a better convention.
I believe svelte is currently missing out on a huge opportunity created by the fact that it is a compiler--the ability to use svelte variables within css and make the css itself reactive. The standard svelte syntax would need to change slightly as single brackets wouldn't work, but it could use double brackets or use the built in css var() function to look something like:
header{
background: {{headerBgColor}}
}
-OR-
header{
background: var({headerBgColor})
}
This is by far the biggest change I am recommending but would easily become one more reason devs love svelte.
In summary, I am suggesting a simple but profound overhaul to styling in svelte by phasing out the :global() selector in favor of 'global' and 'temp' flag attributes on <style> tags as well as allowing the use of reactive variables inside style tags.
Describe the proposed solution
See the main thread
Alternatives considered
See the main thread
Importance
would make my life easier