Allow global scope on v-bind in <style>
What problem does this feature solve?
Allows scoping css and css variables to elements outside vue app (such as body).
<script>
const bgcolor = 'red';
</script>
<template>
<!-- works -->
<component :is="'style'" type="text/css">
body {
--some-var: {{bgcolor}};
background-color: var(--some-var) !important;
}
</component>
</template>
<style>
/* does not work */
body {
--some-var: v-bind(bgcolor);
background-color: var(--some-var) !important;
}
</style>
What does the proposed API look like?
<style global>
What problem does that solve? How is this better than simply assigning a custom property to document.body.style
?
Is the scoping of the variable name solving any naming collision issues you would face with a non-scoped global name? Or wouldn't that rather be a hindrance as we are dealing with global custom properties anyhow, which should likely be changeable from more than one place?
How should the custom property behave when the component is unmounted? Should we remove it? So far there is no lifecycle to styles specifically.
I agree that my problem can be solved in a different way, but it would be a nice-to-have feature to be able to do --my-var: v-bind(color) where --my-var is scoped to body, but considering v-bind generated css vars are scoped to component via inline style I suspect this is not possible with how things work today. I'll move forward with using <component :is="'style'" instead.
@LinusBorg this looks like a bug. As I understand it, the entire purpose of <style scoped>
is to prevent styles from being applied globally... so shouldn't @olemarius 's request be the default behavior?
I suggest we reopen this issue. Vue happily compiles unscoped <style lang="scss">…</style>
containing v-bind(my-variable)
and it's completely non-obvious that my-variable
will not be available when the styles affect HTML elements outside the component's DOM subtree. If v-bind variables are used in unscoped styles, I would expect Vue to set the corresponding CSS variables on the <html>
or <body>
tag instead of on the component's root. But that's obviously just my opinion – one could certainly think of other solutions (a new <style global>
section being one of them).
In any case, the compiler should at least complain that variables might not be available in unscoped styles.
What problem does that solve? How is this better than simply assigning a custom property to document.body.style?
The problem this solves is that I won't have to worry about component mounting/unmounting/reactivity etc. as Vue takes care of that for me. I was manipulating the DOM directly at first, but then noticed that v-bind
would reduce the amount of code quite a bit, only to realize that it doesn't work. :(
Came across the same issue today. Was wondering why v-bind styles weren't applied globally. In my case I have theme colors that change on a page component, and that I want modals and popups to respect, however since they are rendered outside of the page component even though I use :global
the theme variables apply but with undefined values it seems.
This is not a bug.
The actual value will be compiled into a hashed CSS custom property, so the CSS is still static. The custom property will be applied to the component's root element via inline styles and reactively updated if the source value changes.
https://vuejs.org/api/sfc-css-features.html#v-bind-in-css
- There is one CSS custom property name generated at compile time
- This custom property is added to the component's root element
If we add this property to body
, then multiple instances of a component would override each other's custom property, which can then lead to race conditions depending on the order of component mounts and updates.
What you want/would need is something that works very different - you want essentially a dynamic CSS property name, generated at runtime, per component instance, that is dynamically added to and removed from body
during mount/unmount.
This is a feature request that could be proposed and discussed, but it's not a bug in the current implementation, which is explicitly focussed on elements within the component.
However, what we do provide is support with <teleport>
. if you use <teleport>
(usually used with modals etc) in a component, then we do re-apply the custom properties to the wrapper element that you teleported to.
@LinusBorg No, this is indeed not a bug, as you say. But what @olemarius posted was a feature request, so this seems very much in line with what you're saying? :)
(I agree with your assessment of the race condition risk, though. In my case, I have a single top-level "layout" component which interacts with the outside DOM, so for me personally that'd be a risk I'd be willing to take. But I definitely understand your concerns.)