[Vuejs]-Dynamic CSS classes and rules in a VueJS component depending on a table in a database

0๐Ÿ‘

I am not aware of a way in Vue to dynamically add or remove CSS classes. But you can do it in regular JS, by creating a style tag and adding it to the HTML head:

const registerStyles = (id, stylesString) => {
  let styleEl = document.getElementById(id)
  if (!styleEl) {
    const el = document.createElement('style')
    el.type = 'text/css'
    el.id = id
    styleEl = el
    document.head.appendChild(styleEl)
  }
  styleEl.innerHTML = stylesString
}

Here it is in a small snippet:

const { createApp, watch, ref } = Vue;

const colors = ['purple', 'hotpink', 'darkviolet']
const classes = ['foo', 'bar', 'baz']

const buildStyles = () => classes.map(className => {
    const colorIx = Math.random() * colors.length | 0
    const color = colors[colorIx]
    return `.${className}{ background: ${color}; }`
  }).join("\n")

const registerStyles = (id, stylesString) => {
  let styleEl = document.getElementById(id)
  if (!styleEl) {
    const el = document.createElement('style')
    el.type = 'text/css'
    el.id = id
    styleEl = el
    document.head.appendChild(styleEl)
  }
  styleEl.innerHTML = stylesString
}

  
const App = {
  setup(){
    const rebuildStyles = () => {
      const styles = buildStyles()
      registerStyles('mystyles', styles)
    }
    rebuildStyles()
    return {
      rebuildStyles
    }
  }
}
const app = createApp(App)
app.mount('#app')
<div id="app">
  <div class="foo">foo</div>
  <div class="bar">bar</div>
  <div class="baz">baz</div>
  <button @click="rebuildStyles">rebuild styles</button>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

Have a look at how Vuetify does it, they use a library for document head management (@vueuse/head), and use DOM manipulation (as above) as fallback.

0๐Ÿ‘

Since you want to dynamically assign the image URL, I recommend using style binding. With this, you can create an object that contains CSS properties in camel case and assign it to the style prop. Observe:

<script setup>
const buildStyle = (skill) => {
  const image = skill.toLowerCase();
  
  return {
    backgroundImage: `url("https://cdn.jsdelivr.net/gh/devicons/devicon/icons/${image}/${image}-original.svg")`,
    width: '18px',
    height: '18px',
  };
};

const skills = ['VueJS', 'React'];
</script>

<template>
  <main>
    <article v-for="skill in skills" :key="skill">
      <div :style="buildStyle(skill)" />
      {{ skill }}
    </article>
  </main>
</template>

Live Demo

Leave a comment