1

As this QA mentioned, we can make a variable play as a class name in less.

but how to make that in vue?

<script setup>
const uuid = 'data-v-123'
</script>

<style lang="less">
@dynamicVar: xxxx; // how to pass uuid as a less variable?

.@{dynamicVar} {
  color: red;
}

// Or, how to pass a vue variable as a class name?
.[dynamicVar] { // this is the placement I want to inject
  color: red;
}
</style>

Here I have a Popover Component which is being used in every table cloumn:

table-tooltip

I want to make a random string complied as a CSS class name in Vue3 (Vite).

In vue, we can get the component's scope id via Vue's API getCurrentInstance().type.__scopeId, so here is the consensus: the scope id is a unique string, every component have a scope id and difference from others.

So, we can use the scope id as a unique class name for the component, so we have applied it to the component's class list.

But there is a problem: how to define the styles for this unique class name?

We know it is dynamic, and it is unknown to write as a certain string into the <style></style> sheet, until Vite build the code.

here is demo for ElementUi's ElTooltip component. The uuid variable is the thing I want to use as a class name.

You can see, there is a way we can use v-bind:uuid="''", apply the unique calss name as html dataset attribute,

<template>
<el-table :[uuid]="''">
</el-table>
</template>

<script setup>
const uuid = 'data-123'
</script >

<style scoped>
.el-table:deep { // :deep is the scopeId
  background-color: red !important
}
</style>

Vite will complied this into:

<div class="el-table" data-123>
</div>

<style>
.el-table[data-v-123]{ 
  background-color: red !important
}
</style>

But this can't use to ElTooltip, first, you can't use scoped for the style, cause the tooltip component is applied into the body.

Second, the dataset won't be applied into html dataset attribute in this case, perhaps ElementUi filtered it. you can see this in the demo.

So there is only one fantasy left, which is to let Vite compile this variable into a class name.

Well, there is a way to doing this, but not very close to the original thought, that's Vue's module CSS:

<template>
<el-table :class="[{$styles.table}]">
</el-table>
</template>

<style module>
.table{
  background-color: red !important
}
</style>

Vite will complied this into:

<div class="_table_1ok_2">
</div>

<style>
._table_1ok_2{ // somethins like this, just for demo 
  background-color: red !important
}
</style>

Wow, is that the exact what we want? well, sit down. When there are nested styles we need to define:

<template>
<el-tooltip :popper-class="{$styles.table}">
  <div class="text-wrapper">
    <span class="text-inner">
    </span>
  </div>
</el-tooltip>
</template>

<style module>
.el-tooltip{
  background-color: red !important
  .text-wrapper {
    border: 1px solid yellow;
    .text-inner {
      font-size: 24px;
    }
  }
}
</style>

Vite will complied this into:

<div class="_el-tooltip_1ok_2">
  <div class="_text-wrapper_mono1">
    <span class="_text-inner_mmxr">
    </span>
  </div>
</div>

<style>
._el-tooltip_1ok_2{
  background-color: red !important
}
._el-tooltip_1ok_2 ._text-wrapper_mono1 {
  border: 1px solid yellow;
}
._el-tooltip_1ok_2 ._text-wrapper_mono1 ._text-inner_mmxr {
  font-size: 24px;
}
</style>

this is not what we want, we only bind the el-tooltip module class name, not the children's, so we need it been complied into this:

<style>
._el-tooltip_1ok_2{
  background-color: red !important
}
._el-tooltip_1ok_2 .text-wrapper {
  border: 1px solid yellow;
}
._el-tooltip_1ok_2 .text-wrapper .text-inner {
  font-size: 24px;
}
</style>

well, Vue allow us to doing this, if we use :global() commant:

<style module>
.el-tooltip{
  background-color: red !important
  :global(.text-wrapper) {
    border: 1px solid yellow;
    :global(.text-inner) {
      font-size: 24px;
    }
    :global(.Another-Child-Class-Name) {
      // your code
    }
  }
}
</style>

you see, we need to use :global commant wrap the class name. But we can't just wrap only a parent class name, but all class name inside the parent class name. Vite won't treat those children class name as a global style if we don't wrap the global command with them.

Don't you think this is so tedious?

Now we're back to the topic we were discussing earlier. How can we achieve this?

1 Answer 1

0

if you want to use classes only inside that template(file),

consider use 'scoped' property

<style scoped>
.example {
  color: red;
}
</style>

<template>
  <div class="example">hi</div>
</template>

https://vuejs.org/api/sfc-css-features.html#scoped-css

else, if you want to keep the classes name, simply do not use module property, which changes your classes name for keeping them unique.

https://vuejs.org/api/sfc-css-features.html#css-modules

Sign up to request clarification or add additional context in comments.

1 Comment

in this case, we can't use scoped css. because the component ElPopper is the same level with body. there is no scope style you can apply to.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.