vuejs / rfcs

RFCs for substantial changes / feature additions to Vue core
4.87k stars 546 forks source link

SFC style CSS variable injection (new edition) #231

Closed yyx990803 closed 3 years ago

yyx990803 commented 3 years ago

This is an improved alternative of the previous version (<style vars> as proposed in #226)

Thanks to feedback by @Demivan and @privatenumber, #226 has a few notable issues that can be improved:

  1. Requires manual vars declaration for exposing variables that can be used.
  2. No obvious visual hint that a variable is injected and reactive
  3. Different behavior in scoped/non-scoped mode.
  4. In non-scoped mode, the CSS variables would leak into child components.
  5. In scoped mode, the global: prefix is required to use normal CSS variables declared outside of the component. It would be preferable that normal CSS variable usage stays the same in/out of the component.

This proposal addresses all of the above with the following usage:

<template>
  <div class="text">hello</div>
</template>

<script>
  export default {
    data() {
      return {
        color: 'red',
        font: {
          size: '2em'
        }
      }
    }
</script>

<style>
  .text {
    color: v-bind(color);

    /* expressions (wrap in quotes) */
    font-size: v-bind('font.size');
  }
</style>

Summary:

Rendered

CyberAP commented 3 years ago

What do you think about writing those bindings without -- prefix, so we can better distinguish them from the native CSS Custom Properties?

<script>
export default {
  data() {
    return { baz: 'red' }
  }
}
</script>

<style>
.foo {
  color: var(:bar); /* binding */
  font-size: var(--global-font-size); /* native property */
}
</style>

We don't reference those transformed bindings in the code so they don't really require -- prefix.

Also, to avoid Prettier issues the --: prefix could be replaced with a # (also works for CSS parsers), though it might be confusing since url(#foo) can reference SVG path.

<style>
.foo {
  color: var(#bar); /* won't be affected by Prettier */
}
</style>
yyx990803 commented 3 years ago

@CyberAP I think it's better to keep the leading -- because it's a smaller spec mismatch than without it:

  1. --:foo can still be considered a custom property identifier that contains an invalid char
  2. :foo is not a custom property identifier (which is defined as an identifier with leading --) - in fact, CSS identifier tokens cannot start with :.

I think (2) has a higher risk of tooling incompatibility as it's more likely for a parser to fail to tokenize :foo as an identifier due to the invalid leading char.

privatenumber commented 3 years ago
// Button.vue - example of a themable component reading from an injected state
<template>
    <button class="button">
        <slot />
    </button>
</template>

<script>
export default {
    inject: ['theme'],
};
</script>

<style>
.button {
    background-color: var(--:theme.color.primary);
}
</style>
// Input.vue - another example of a themable component reading from an injected state
<template>
    <input
        class="input"
        type="text"
    >
</template>

<script>
export default {
    inject: ['theme'],
};
</script>

<style>
.input {
    color: var(--:theme.color.primary);
}
</style>
// Layout.vue - injects theme state, and also has UI that rapidly updates theme properties
<template>
    <div class="layout">
        <label>
            Primary color:

            <!-- Every change here will update a different CSS var for each component that reads from this  -->
            <input
                type="color"
                v-model="theme.color.primary"
            >
        </label>

        <slot />
    </div>
</template>

<script>
export default {
    data() {
        return {
            theme: {
                color: {
                    primary: 'red',
                },
            },
        };
    },

    provide() {
        return {
            theme: this.theme,
        };
    },
};
</script>
xstxhjh commented 3 years ago

font-size: var(--:font.size); : .
vscode problems: ) expectedcss(css-rparentexpected)

Invalid CSS Var

:root {
  --font.size: 22px;
}

.text {
  font-size: var(--font.size);
}

valid CSS Var

:root {
  --fontSize: 22px;
}

.text {
  font-size: var(--fontSize);
}

will go wrong?

.text {
    color: var(--v-bind:color);

    /* shorthand + nested property access */
    font-size: var(--:font.size);
}
ghost commented 3 years ago

What's the reason of having both long and shorthand notation? Just pick one...

Kocal commented 3 years ago

@web2033 We have v-bind:attr and :attr in templates, so it makes sense

CyberAP commented 3 years ago

From my personal experience v-bind is never used in projects in a long notation and having two types of notation has never been great because people have to choose one when framework should actually solve that problem for them.

ghost commented 3 years ago

How about

.text {
    color: var(--v-bind-color);
    font-size: var(--v-bind-font-size);
}

since a finger is already on - anyways. Valid CSS. No tooling tweaking needed.

ghost commented 3 years ago

... or "vue-branded" vars 😁

<template>
  <div class="text">hello</div>
</template>

<script>
  export default {
    data() {
      return {
        color: 'red',
        font: {
          size: '2em'
        }
      }
    }
</script>

<style>
.text {
    color: var(--vue-color);
    font-size: var(--vue-font-size);
}
</style>
yyx990803 commented 3 years ago

@privatenumber the theme injection is an example, and yes it can potentially lead to inefficiency when used everywhere. Maybe for global themes it is still better to provide it as plain CSS variables at root and let it cascade:

<!-- App.vue -->
<script>
const theme = ref({
  color: 'red',
  // ...
})
</script>

<template>
  <div class="theme-provider>
    <input type="color" v-model="theme.color">
  </div>
</template>

<style>
.theme-provider {
  --color-primary: var(--:theme.color);
}
</style>
yyx990803 commented 3 years ago

@xstxhjh ok so I tested this within an SFC with an experimental extension that did not have strict CSS linting... turns out having : and . inside a variable name does create issues.

So maybe instead we can just use a custom CSS function instead of var():

.text {
  font-size: v-bind(color);
}

In order to use expressions that contain invalid CSS indentifier chars inside, wrap it with quotes:

.text {
  font-size: v-bind('theme.color.primary');
}
yyx990803 commented 3 years ago

Revised to use v-bind() function instead - this should be valid CSS syntax that is compatible with any tooling.

CyberAP commented 3 years ago

This is much better now!

replygirl commented 3 years ago

When I was using the first version of <style scoped vars> I saw it as a powerful way to extend a Stylus theming system I've been using across most of my projects that uses classes to apply a bunch of CSS variables at different scopes. I wasn't able to do this in reality, because of the scoping applied to the variable names themselves (though I could have used a second, non-scoped stylesheet and a more specific selector)

This proposal makes variable injection perfect for a partially CSS-in-JS type of theming approach like you showed, but the function approach would make directly overriding CSS variables on a case-by-case basis a bit unwieldy with v-bind acting as a middleman. Maybe this is better, though, because it encourages you to commit to a consistent paradigm for the most part

Recycling v-bind feels weird to me, idk. @web2033's prefixing solution makes a little more sense to me—There's semantic parity with how cli handles environment variables. And calcs keep a bit cleaner

Dedicatus546 commented 3 years ago

it seems that i could‘t compress all css file?it seems that <style vars> generate css by js because i see it use variables from data return object in the example

yyx990803 commented 3 years ago

@1607611087 the generated CSS file is static and compatible for compression. It generates rules using hashed CSS variables which are injected at runtime onto DOM nodes as inline styles by Vue.

Dedicatus546 commented 3 years ago

@yyx990803 inline style? emmm... it looks like complex for developer if there are many many many inline style on a node.

why not has two way like <style vars> and <style> just like <script setup> and <script>?

<style> is same as before <style vars> can use variables from data or setup return object, and generate a CSS class with a independent attribute (like data-v-xxxx) and a original attribute, and then dynamically insert it wrapped <style> to DOM

<style>
.text {
  /* static style */
}
</style>

<style vars>
.text {
  color: v-bind(color);
  font-size: v-bind('font.size');
}
</style>

after generate

<style>
/* other static css style*/

.text[data-v-xxxxabcd]{
  /* static style */
}
</style>

<style>
/* dynamically generate */
.text[data-v-xxxxabcd][data-v-xxxxefgh]{
  color: red;
  font-size: 14px;
}
</style>
Justineo commented 3 years ago

@1607611087 Dynamically generating a <style> element will be much more expensive than precisely changing values of related CSS custom properties. See the benchmark here.

Dedicatus546 commented 3 years ago

@Justineo sorry,i dont consider this problem😂. Dynamically generating a <style> element exactly has a low performance.

yyx990803 commented 3 years ago

This RFC is now in final comments stage. An RFC in final comments stage means that:

The core team has reviewed the feedback and reached consensus about the general direction of the RFC and believe that this RFC is a worthwhile addition to the framework.

Final comments stage does not mean the RFC's design details are final - we may still tweak the details as we implement it and discover new technical insights or constraints. It may even be further adjusted based on user feedback after it lands in an alpha/beta release.

If no major objections with solid supporting arguments have been presented after a week, the RFC will be merged and become an active RFC.

b-strauss commented 3 years ago

Will this work with css custom properties?

.foo {
  --main-color: v-bind(color);
}
yyx990803 commented 3 years ago

@b-strauss yes it works.

The syntax is now usable with vue@^3.0.3 + vite@^1.0.0-rc.13 or vue-loader@next.

tavrez commented 3 years ago

Can this be used in this form?

p:nth-child(v-bind(child)) {
  background: red;
}
leopiccionia commented 3 years ago

@tavrez I'm not sure if this is a syntactically-valid placement for a CSS custom property (a.k.a. variable), so I'd guess not, at least for now.

talmand commented 3 years ago

I may be late to the party here, but I have to say as a UI dev I was more interested in the previous version of this concept. I would suggest that this version goes against the nature of CSS variables, removes some of their usefulness, and prevents using the fallback nature of the second parameter of the var() function in CSS.

CSS variables are supposed to "leak" into the child elements (or components as you will) as they follow the cascading part of CSS. Attempting to prevent this feature actually makes using CSS vars more complicated. If I wanted to keep the cascading feature I would now have to pass the data along to children components instead of relying on the cascade, which is far more efficient. Even then, the CSS variables of the parent component are inherited by the child component (you can see them in the devtools) but they can't be used. If the same data is passed down for the child component to create its own CSS variables there will be multiple CSS variables with the same value available to the child component. That would mean that grandchildren or even great-grandchildren will have who knows how many references to CSS variables being inherited that cannot be used; which mucks up the devtools display.

In the previous version of this concept I had several tests built trying different things. I was using props, data object variables, and setup function returning variables. Each of these worked very well with the vars attribute as I was just feeding it an object that I built however I felt. Then just referenced the variables inside the var() CSS function. It could be how I have my first tests of this version working right now, but I can only seem to get it to work with data object variables in the Options API.

Props usage spits out this error:

Uncaught (in promise) ReferenceError: __props is not defined

Trying to use the Composition API I get this error:

Uncaught (in promise) ReferenceError: _unref is not defined

Again, this could be my fault somehow as I just started tinkering with this version. I'm just trying to pass along the same object in each of those cases. I would try to create an example on CodePen but for some reason they still have the compiler that expects the vars attribute version.

In the current version the v-bind has taken away the var() function altogether and to get it back requires creating yet more CSS variables that take in the reactive-based CSS variables to provide expected functionality such as the fallback:

--myColor: v-bind('myReactiveColor');
color: var(--myColor, black);

As someone who is currently working on a design system that has heavy usage of CSS variables, I can't see how this feature helps me in that endeavor. The previous version easily allowed for global CSS variables to be overridden at the component level with just props if needed, a component reacting to changes to use existing CSS variables to update styles, and have those changes cascade downward; all with very little setup or overhead. I can see this ability being very useful, the current version is far more restrictive in my opinion.

talmand commented 3 years ago

After pondering over this I have two suggestions that could alleviate my concerns above.

How about an optional property for the component much like inheritAttrs? This property, named something like prefixCssVars, would default to true and the CSS variables are created with their prefixes as currently working. On the other hand, if the property is set to false in the component then the CSS variables are created without prefixes allowing for the cascading feature. I can understand the desire to scope CSS variables just to the component, but I would think the option to leverage a basic feature of CSS variables would also be desirable.

Maybe as a parameter of the v-bind so the prefix can be controlled on a per CSS variable basis?

Since v-bind is a function inside the style block would it be possible to allow for another parameter, that expects a string, that is placed as the fallback in the created CSS var function? For instance, color: v-bind('myColor', 'black'); would be outputted as color: var(--myColor, black);. This would even potentially allow for something like color: v-bind('myColor', 'var(--myDefaultColor)');, which would allow for using CSS variables as the fallback. Granted this feature's usefulness depends on the ability to cancel out the variable in the v-bind so that the fallback would be used. In the vars attribute version I was doing this by assigning null as the value to be passed along which prevented the CSS variable from being created.

yyx990803 commented 3 years ago

@talmand

First of all: this feature is not about enhancing CSS variables. It's about injecting state-driven values into your CSS. CSS variables just happen to be the underlying implementation detail.

With that in mind, it doesn't make sense for the bindings to "leak". If you want them to leak, just bind them to an actual CSS variable that "leaks":

.foo {
  --myColor: v-bind(myReactiveColor);
}

And if you want a fallback, note that v-bind can actually accept JavaScript expressions:

.foo {
  --myColor: v-bind('myReactiveColor || "black"');
}
CyberAP commented 3 years ago

I'd really wish for CSS and JS code to be separated from each other, i.e. for v-bind to be able to accept only a context reference without proper support for full js expressions.

.foo {
  color: v-bind(bar); /* valid */
  color: v-bind('baz.qux'); /* valid */
  color: v-bind('1+1'); /* invalid */
}

It's not a pleasant experience if your logic is split up from the main component's code (where you actually can place exactly the same expression in a form of computed).

talmand commented 3 years ago

I didn't really see this as a means to enhance CSS variables, but exactly as you say; to leverage a useful feature of CSS that allows for dynamic changes to the styles without requiring a compiling of files. This is an excellent use of the CSS feature to enhance features of Vue. This kind of thing was already being done via injecting style attributes on elements in the component; this feature takes away the overhead of doing that.

The only real disagreement I have is to permanently prevent an established behavior and feature of CSS variables. Cascading is part of the spec and I would wonder why there shouldn't even be an option to allow it if the dev wishes the cascade to happen. That is, an option that doesn't require overhead in the style block to handle it.

In the end, we'll learn to leverage the feature as we need in ways we are unable to foresee at this time.

Matt-Deacalion commented 3 years ago

Does this work with ref? I haven't been able to make it work in Vue 3.0.0, but I can get it working if I use reactive.

<template>
    <h1>Green text!</h1>
</template>

<script>
import { reactive } from 'vue';

export default {
    name: 'App',

    setup() {
        // …this works
        return { ...reactive({ colour: 'green' }) };

        // …but this does not
        // return { colour: ref('green') };
    },
}
</script>

<style>
h1 {
    color: v-bind('colour');
}
</style>
AndrewBogdanovTSS commented 3 years ago

@Matt-Deacalion works with refs for me, using it with Vue 3.0.5. I also tried it with setup attribute and seems like it also works fine:

<script setup>
  const testColor = 'blue'
</script>
<style lang="postcss">
  .test {
    color: v-bind(testColor);
  }
</style>
Matt-Deacalion commented 3 years ago

@AndrewBogdanovTSS Still no luck with Vue 3.0.5. Interestingly it does work if I use the new <script setup> syntax.

cxdev commented 3 years ago

The syntax is cool ! Can I use it with teleport ? it doesn't work:

<script lang="ts">
import { defineComponent, inject } from 'vue'
import { Viewer } from 'cesium'
export default defineComponent({
  name: 'ViewerPopup',
  inheritAttrs: false,
  props: {
    top: {
      type: String,
      required: false
    },
    left: {
      type: String,
      required: false
    },
    show: {
      type: Boolean,
      default: true
    }
  },
  setup () {
    const viewer = inject<Viewer>('viewer')
    const queryWidget = viewer.cesiumWidget.container // dom容器

    return {
      queryWidget
    }
  }
})
</script>

<template>
  <teleport :to="queryWidget">
    <div
      v-show="show"
      class="vum-popup-x"
      v-bind="$attrs"
    >
      <slot></slot>
    </div>
  </teleport>
</template>
<style>
.vum-popup-x {
  position: absolute;
  z-index: 1;
  top: v-bind(top);
  left: v-bind(left);
}
</style>
AndrewBogdanovTSS commented 3 years ago

@cxdev why should it work with teleport feature? If you investigate how this feature works under the hood you will see that it is placing a specific identifier on the parent node and applies css of the child nodes via it. Teleport moves nodes under completely different parent - so it won't match a selector anymore. If you want to use teleport and still have access to this feature you should create a wrapper component specifically for teleporting

cxdev commented 3 years ago

@AndrewBogdanovTSS I see, Thanks! I just want to move the componet in a more appropriate (like a button in widget-container) container which preset by a third party. Is there a better way to do this? in addition, I tried rollup a .vue file which use the syntax in style, rollup.config:

import { nodeResolve } from '@rollup/plugin-node-resolve'
import path from 'path'
import vuePlugin from 'rollup-plugin-vue'
import css from 'rollup-plugin-css-only'
const { entry } = require('./common')

export default [
  {
    input: path.resolve(__dirname, `../packages/${entry}/index.ts`),
    output: {
      format: 'es',
      file: 'lib/index.esm.js'
    },
    plugins: [
      nodeResolve(),
      css({
        output: 'index.esm.css'
      }),
      vuePlugin({
        css: false
      })
      // ....
    ],
    external: ['vue']
  }
]

output index.esm.css

.test{
  ...
  cursor: v-bind(cursor);
}

it seems the .css can't get the injectCSSvars

lanthaler commented 3 years ago

[...] And if you want a fallback, note that v-bind can actually accept JavaScript expressions:

.foo {
  --myColor: v-bind('myReactiveColor || "black"');
}

@yyx990803 I wonder whether it would be worthwhile to add an optional second parameter to v-bind to simplify specifying the unit without having to resort to string concatenation if the reactive variable is a number:

.foo {
  --mySize: v-bind(myReactiveSize, "px");
}

instead of

.foo {
  --mySize: v-bind('myReactiveSize + "px"');
}
petterw03 commented 3 years ago

Is there a reason for this functionality not working with props or is it a bug? Using props would be my main use case - sending for example color down to a component and then use the color to dynamically change the style.

brian-sea commented 3 years ago

Sometimes, I can access props... but it's not consistent. Maybe the CSS-var resolution is done too early in the lifecycle?

daiwanxing commented 3 years ago

Does anyone knows why writing like this doesn't work ? I get the error : _unref is not defined Thanks..

<script>
export default {
    setup () {
        return {
            color: "red"
        }
    }
}
</script>
<style scoped>
h1 {
    color: v-bind(color);
}
</style>
mattersj commented 3 years ago

Well, as I understand it works only with data property, buuut.. let's be honest, who cares about old-fashioned Options API in Vue 3? Why wouldn't use props and setup as well? Personally, I've used data in Vue 3 about 0 times and something tells me that it's not just me. I'd really like to see some obvious improvements in the current implementation.

AndrewBogdanovTSS commented 3 years ago

Well, as I understand it works only with data property, buuut.. let's be honest, who cares about old-fashioned Options API in Vue 3? Why wouldn't use props and setup as well? Personally, I've used data in Vue 3 about 0 times and something tells me that it's not just me. I'd really like to see some obvious improvements in the current implementation.

using data property is not "old-fashioned" in any way. If you don't use it - it doesn't mean no one else doesn't. I don't understand why you thought it's working only with data in the first place. I used it with "new" setup syntax and it worked perfectly fine

mattersj commented 3 years ago

using data property is not "old-fashioned" in any way. If you don't use it - it doesn't mean no one else doesn't.

I didn't say no one uses Options API in Vue 3, but I'm pretty sure that most people prefer to use the Composition API if they already picked the Vue 3.

I used it with "new" setup syntax and it worked perfectly fine

Could you please provide the reproduction example? Here is mine: https://github.com/mattersj/vue-css-vars Neither props nor setup does work, as I said before.

In my example HW component (with props) throws the following error: Uncaught (in promise) ReferenceError: __props is not defined Whereas the second HW2 component (with setup) throws this one: Uncaught (in promise) ReferenceError: _unref is not defined.

nesteiner commented 3 years ago

在style中绑定变量后,给这个变量设置setInterval实时更新,但是样式没有变化诶
比如这里修改 opacity 属性

<template>
  <div class="shining">
    <h1> Vue </h1>
  </div>
</template>

<script lang="ts">
 import {Vue} from 'vue-property-decorator'

 export default class Shining extends Vue {
   private opacity: number = 0

   mounted(): void {
     setInterval(() => {
       this.opacity >= 1 && (this.opacity = 0)
       this.opacity += 0.2
     }, 300)
   }
 }
</script>

<style scoped>
 h1 {
  /* color: rgb(65, 284, 131); */
   color: black;
   opacity: v-bind(opacity);
 }
</style>

但是如果使用js写的话,没有这个问题

 export default {
   data() {
     return {
       opacity: 0
     }
   },

   mounted() {
     setInterval(() => {
       this.opacity >= 1 && (this.opacity = 0)
       this.opacity += 0.2
     }, 300)
   }
 }
3N26 commented 3 years ago

how i can use v-bind in background-image: url()

<template>
  <div class="bg" />
</template>

<script setup>
const img = "https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png";
</script>

<style scoped>
 .bg {
   --img: url(v-bind(img));
   --img2: url("https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png");
   width: 100vw;
   height: 100vh;
   background-image: url(v-bind(img)); /* no work */
   background-image: var(--img); /* no work */
   background-image: var(--img2); /* work */
 }
</style>
daiwanxing commented 3 years ago

how i can use v-bind in background-image: url()

<template>
  <div class="bg" />
</template>

<script setup>
const img = "https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png";
</script>

<style scoped>
 .bg {
   --img: url(v-bind(img));
   --img2: url("https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png");
   width: 100vw;
   height: 100vh;
   background-image: url(v-bind(img)); /* no work */
   background-image: var(--img); /* no work */
   background-image: var(--img2); /* work */
 }
</style>

Just write like this, It's wrting similar to the css var function.

<script setup>
const img = "url(https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png)";
</script>

<style scoped>
 .bg {
   background-image: v-bind(img)
 }
</style>
nesteiner commented 3 years ago

@chenxinan 试试这个

<script>
import img from 'path'
export default {
    data() {
        img,
    }
}

</script>
0x1af2aec8f957 commented 3 years ago

在style中绑定变量后,给这个变量设置setInterval实时更新,但是样式没有变化诶 比如这里修改 opacity 属性

<template>
  <div class="shining">
    <h1> Vue </h1>
  </div>
</template>

<script lang="ts">
 import {Vue} from 'vue-property-decorator'

 export default class Shining extends Vue {
   private opacity: number = 0

   mounted(): void {
     setInterval(() => {
       this.opacity >= 1 && (this.opacity = 0)
       this.opacity += 0.2
     }, 300)
   }
 }
</script>

<style scoped>
 h1 {
  /* color: rgb(65, 284, 131); */
   color: black;
   opacity: v-bind(opacity);
 }
</style>

但是如果使用js写的话,没有这个问题

 export default {
   data() {
     return {
       opacity: 0
     }
   },

   mounted() {
     setInterval(() => {
       this.opacity >= 1 && (this.opacity = 0)
       this.opacity += 0.2
     }, 300)
   }
 }

@nesteiner doc: https://github.com/vuejs/rfcs/blob/sfc-improvements/active-rfcs/0000-sfc-style-variables.md#motivation

edisdev commented 3 years ago

@privatenumber the theme injection is an example, and yes it can potentially lead to inefficiency when used everywhere. Maybe for global themes it is still better to provide it as plain CSS variables at root and let it cascade:

<!-- App.vue -->
<script>
const theme = ref({
  color: 'red',
  // ...
})
</script>

<template>
  <div class="theme-provider>
    <input type="color" v-model="theme.color">
  </div>
</template>

<style>
.theme-provider {
  --color-primary: var(--:theme.color);
}
</style>

Hi @yyx990803 🖐 i did make a small example for latest version this feature. (with v-bind) 👉 The gist link is also here.

I hope that will be useful. 🙏

<template>
  <div class="Example">
    <div class="area">
      <div class="form">
        <label>Select Color</label>
        <input type="color" v-model="customTheme.bgColor" />
      </div>
      <div class="preview">
        <span>{{ customTheme.bgColor }}</span>
        <div class="customColor"></div>
      </div>
    </div>
  </div>
</template>

<script>
import { ref } from "vue";
export default {
   setup() {
    const customTheme = ref({
      bgColor: "",
    });
    return {
      customTheme
    };
  },
};
</script>

<style>
.Example {
  --custom-color: v-bind("customTheme.bgColor");
}
.customColor {
  background: var(--custom-color);
  width: 100px;
  height: 50px;
}
</style>
m4heshd commented 3 years ago

Amazing. Is SCSS compatible with this feature?

ITenthusiasm commented 3 years ago

Amazing. Is SCSS compatible with this feature?

@m4heshd I think so. When I tried to test out the experimental feature while working on a Vue 3 project, it seemed to work fine while using scss for the style section.