1

There are several questions with good answers here regarding how to conditionally add classes to an element, or how to conditionally add styles to an element, but what I'd like to do is conditionally style a class.

I have an application with its own theming system which allows the users to select custom foreground and background colors. I'd like to then apply those colors to quill.js toolbar buttons. If I knew the colors in advance, I could add something like this to my styles.

.ql-toolbar .ql-stroke {
    stroke: #f00;
}

I could even optionally throw a conditional class on my container and have multiple child styles in my template.

.ql-container.foo {
    .ql-toolbar .ql-stroke {
        stroke: #f00;
    }
}
.ql-container.bar {
    .ql-toolbar .ql-stroke {
        stroke: #b4c;
    }
}

But since the users can pick any rgb color, I can't do this.

I've also tried writing a style tag to the component template, but this fails when trying to compile.

Right now, in order to make things work I'm reduced to using document.querySelector to access the toolbar and change the property of each buttons svg elements when the users color settings change. This is an ugly hack, and it can't handle intermittent styles such as active / hover states.

Does anyone know a better way?

roryok
  • 9,325
  • 17
  • 71
  • 138

2 Answers2

1

The answer, I learned from this post, is to use CSS variables, which can be passed in through a style binding.

<template>
   <div class="container" v-bind:style="{'--toolbarColor': toolbarColor}">
      <!-- quill goes here -->
   </div>
</template>

<style>
    .ql-toolbar {
        background-color: var(--toolbarColor) !important;
    }
</style>

<script>
    export default {
        computed: {
            toolbarColor() {
                return '#f00';
            }
        }
    }

</script>

roryok
  • 9,325
  • 17
  • 71
  • 138
0

You can achieve this using styled-components

or if you don't want to set all this up by yourself use the vue-styled-components

const StyledDiv = styled.div`
  flex: 1;
  ${props =>
    props.justifyContent &&
    css`
      justify-content: ${x => x.justifyContent};
    `};
  ${props =>
    props.padd &&
    css`
      padding: 24;
    `};
`;

in vue template

<styled-div padd justifyContent="flex-start" ></styled-div>
keysl
  • 2,127
  • 1
  • 12
  • 16