I'm trying to set opacity of HSLA background color dynamically using CSS variables.
First I created a variable --color
for color, which has --alpha
variable in it as alpha. It works, but I am not able to override the --alpha
variable at element level. The --alpha: .5
on h1
tag is applied to the element, but i am not seeing the transparency on the element.
REPL here: https://svelte.dev/repl/d4e15ba129324149915c2e124eeecb76?version=3.59.1
<script>
let name = 'world';
</script>
<h1 style="--alpha: .5">Hello {name}!</h1>
<style>
:global(:root) {
--alpha: 1;
--color: hsla(225, 50%, 50%, var(--alpha));
}
h1 {
background-color: var(--color);
}
</style>
Because the variable is defined on a different element, higher in the tree, the change to --alpha
will not affect --color
as that is resolved at a different level with a different --alpha
value.
One way around that would be to define the variables on all elements in the component (would not recommend using :global
if it can be avoided, if some children in another component rely on this it may be necessary though).
* {
--alpha: 1;
--color: hsla(225, 50%, 50%, var(--alpha));
}
For scoped styles the selector is turned into just a class selector in the form .svelte-[hash]
but for global styles it might be best to avoid this approach if it negatively impacts performance.
A more optimized way if you need :global
would be to move just the color declaration to a special class which then needs to be applied on elements where the --color
is being referenced (in this case the h1
or any child components):
:global(.custom-color) {
--color: hsla(225, 50%, 50%, var(--alpha));
}
If you extract all other color components (hue, saturation, lightness) and drop --color
altogether, you could avoid this situation, though you also would always have to spell out a lengthy hsla
definition everywhere.