Conditionally override css in Style tag - vue.js

Assuming I am using a plugin that generates html at runtime where I cannot edit the CSS or JS code, leaving me with the only option of overriding certain CSS in particular classes. For instance, in such case I'd often do:
.video-player{
max-height: 500px !important;
}
In case such styling must be handled conditionally based on the props passes to the component, for instance:
<videoPlayer :goSmall="anotherColumn != null"></videoPlayer>
since the CSS in the videoPlayer components must go in the Style tag:
<style scoped>
.video-player{
max-height: 500px !important;
}
</style>
how can I render it conditionally?
It is such a bad idea to append it to the DOM using lifecyle hooks, so please do not suggest anything like that.

Why not apply a specific class to the component instead of passing a prop?
<videoPlayer :class="{ small: anotherColumn != null }"></videoPlayer>
And the css
<style scoped>
.video-player.small {
max-height: 500px !important;
}
</style>

If you are not okay with dynamically applying CSS using lifecycle hooks. You can always box your components. Make two components for your videoPlayer, we'll call them videoPlayerOriginal and videoPlayerSmall.
//videoPlayerOriginal.vue
<videoPlayer></videoPlayer>
Add your css in videoPlayerSmall.vue
//videoPlayerOriginal.vue
<videoPlayer></videoPlayer>
<style scoped>
.video-player{
max-height: 500px !important;
}
</style>
Now render either one of them conditionally.

Related

How to apply a body {} style to specific vue component

I'm using scoped style for most of my components to not interfere with other components.
Some of my views/components need body { overflow: hidden; }, but others don't.
I can't use
<style scoped>
body {
overflow: hidden;
}
...
</style>
How can i apply this style when specific components are loaded? (i am using vue router if that helps)
You may send a prop to your component like described in here: https://v2.vuejs.org/v2/guide/components-props.html
Let's call you prop isOverflowHidden, and create .hidden class in your css.
After that, you can add your wrapper element (first tag in component) :class="{ hidden: isOverflowHidden }"
Or you can move it to a method.
If you want you can use this this action for inline-styling.
<div :style="{ overflow: (isOverflowHidden ? 'hidden' : '')}"></div>
You can read extended information in here: https://v2.vuejs.org/v2/guide/class-and-style.html#Binding-Inline-Styles

deep selector for changing background color

I've been trying to change the background color of the popover body but it's not changing the color. If I remove scoped from styles then it works but when I use scoped and use deep selector, the color doesn't apply.
This is my code
<template>
<div>
<button
:id="callToAction"
>click me
</button>
<b-popover
:target="callToAction"
triggers="click blur"
custom-class="my-popover-class"
>
<div>Edit Me</div>
</b-popover>
</div>
</template>
<style scoped>
*>>>.my-popover-class {
background: black !important;
color: white !important;
}
*>>>.my-popover-class .popover-body {
color: white !important;
background: black !important;
}
</style>
I am familiar with this issue because I use Bootstrap-vue for almost all of my projects.
If I have to override any of the bootstrap components, I just simply remove the scoped from style. If you need to use scoped and also want to override bootstrap components then you should select its wrapper selector and nest it.
For the first selector, you shouldn't need a deep selector, as the class is added to the root element of the popover, which has the data-v-**** attribute from the scoped tag.
The second one you'll need one, but you need to place it after .my-popover-class. That way your selector will be rendered as .my-popover-class[data-v-****] .popover-body, which should work.
<style scoped>
.my-popover-class {
background: black !important;
color: white !important;
}
.my-popover-class >>> .popover-body {
color: white !important;
background: black !important;
}
</style>
Example on codesandbox

How to pass css styles to plugins in Vue?

I use Vue-Editor.
<vue-editor id="editor" ref="editor" v-model="content" :use-custom-image-handler="true" #image-added ="added" #image-removed ="deleted" :key="componentKey"/>
On mobile devices, the icons are to small. I like to increase the icons size on mobile devices, but on medium devices, I like to keep the default size.
If I do it in this way, the size changes for all pages not only for the current page:
<style>
.p {
color: black
}
.ql-snow.ql-toolbar button {
height: 35px !important;
width: 35px !important;
}
.quillWrapper .ql-snow.ql-toolbar button svg {
width: 35px !important;
height: 35px !important;
}
</style>
If I do it with <style scoped> it doesn't pass the css to the plugin component.
How I can change the css for the plugin only in one Vue component without having a global effect?
You can keep scoped but then, you need to make a deep selector like >>> .ql-snow.ql-toolbar button to select the 3rd party library.
If using SASS, use ::v-deep, more details here.

background property not working in Vue.js

Background properties are somehow not working inside my scss file, all other properties do work.
when i use this for example
scss file:
body {
background: #202020;
font-size: 62.5%;
}
browser never returns background (i tested this with different elements and files):
body {
font-size: 62.5%;
}
I use the standard Vue installation which is suitable with scss/css/sass
I include my scss files inside my main.js file like this
import './assets/scss/main.scss'
I also tried using it inside a scoped tag
<style lang="scss" scoped>
.layout { background: red; height: 100vh; }
</style>
but only the height applied
import inside style tag doesn't work either
<style lang="scss">
#import "../assets/scss/main.scss";
</style>
I know it sounds like a stupid typo or something but i can assure you it's not.

Customizing Buefy with SASS in vue.js

I'm a beginner at this and I'm struggling with changing style for buefy elements. In particular the buefy tabs.
In my component, I've got this style:
<style lang="scss" scoped>
// Import Bulma's core
#import "~bulma/sass/utilities/_all";
// Set your own stuff
$my-primary: red;
$link: red;
$colors: (
"primary": ($min-primary, $primary-invert)
);
$tabs-toggle-link-border-color: red;
$tabs-toggle-link-border-style: red;
$tabs-toggle-link-hover-background-color: red;
$tabs-toggle-link-hover-border-color: red;
$tabs-toggle-link-active-background-color: red;
$tabs-toggle-link-active-border-color:red;
$tabs-toggle-link-active-color: $link-invert !default;
// Import Bulma and Buefy styles
#import "~bulma";
#import "~buefy/src/scss/buefy";
</style>
And my tab is formatted like this:
<b-tabs type="is-toggle" size="is-medium" expanded>
The link color and the primary color are changed like expected. But the tabs remain in their original color.
There are two things I find strange:
If I move this styling to App.vue and remove the "scoped" - the styling does
not work. However - the primary color and the link color changes to purple (not turquoise like I'd expected and which it does if I just remove the $colors from within the component). I thought all styling added to App.vue would work in all components?
Why does not the tabs change color? Have I got the wrong variables? How do I find the right variables? The variables used here is found in bulma/sass/components/tabs.sass.
Both node-sass and sass-loader are installed.
Hope somebody can make me feel a bit more enlightened.
Edit: it turns out, there is a way how to get it working with scoped styles. For that all you need is to wrap #import statements into /deep/ selector:
<style lang="scss" scoped>
... // everything else remains the same
/deep/ {
// Import Bulma and Buefy styles
#import "~bulma";
#import "~buefy/src/scss/buefy";
}
Original answer
Even though this it's a bit old question, I faced the same problem recently with dropdown component.
Variables in original code are correct, but it does not work due to scoped styles. Since #import is called in scoped context, it will be also scoped and thus CSS will not match HTML.
Assuming that original code in tab component is something like this:
$tabs-border-bottom-color: $border !default
$tabs-border-bottom-style: solid !default
$tabs-border-bottom-width: 1px !default
.tabs
#extend %block
+overflow-touch
#extend %unselectable
align-items: stretch
display: flex
font-size: $size-normal
justify-content: space-between
overflow: hidden
overflow-x: auto
white-space: nowrap
a
align-items: center
border-bottom-color: $tabs-border-bottom-color
border-bottom-style: $tabs-border-bottom-style
border-bottom-width: $tabs-border-bottom-width
....
After compiling Vue loader will add [data-v-xxxxxxx] so it will look:
.tabs[data-v-xxxxxx] {
// styles go here
}
but html for tabs is not scoped and this is the reason why it does not work.
One way to get it working would be to remove scoped, but wrap all your styles
into some class name to keep all css private for the component. Assuming that template root element has class my-component-wrapper, scss will be following:
<style lang="scss" scoped>
.my-component-wrapper {
// Import Bulma's core
#import "~bulma/sass/utilities/_all";
// Set your own stuff
$my-primary: red;
$link: red;
$colors: (
"primary": ($min-primary, $primary-invert)
);
$tabs-toggle-link-border-color: red;
$tabs-toggle-link-border-style: red;
$tabs-toggle-link-hover-background-color: red;
$tabs-toggle-link-hover-border-color: red;
$tabs-toggle-link-active-background-color: red;
$tabs-toggle-link-active-border-color:red;
$tabs-toggle-link-active-color: $link-invert !default;
// Import Bulma and Buefy styles
#import "~bulma";
#import "~buefy/src/scss/buefy";
}
</style>
Worth noting that you do not have to import bulma and buefy for each component, it's better to import main/general styles in main file and then import only necessary components (#import "~bulma/sass/components/tabs";).