Vue.js style v-html with scoped css - vue.js

How can I style v-html content with scoped css using vue-loader?
Simple example:
component.vue
<template>
<div class="icon" v-html="icon"></icon>
</template>
<script>
export default {
data () {
return {icon: '<svg>...</svg>'}
}
}
</script>
<style scoped>
.icon svg {
fill: red;
}
</style>
generate html
<div data-v-9b8ff292="" class="icon"><svg>...</svg></div>
generate css
.info svg[data-v-9b8ff292] { fill: red; }
As you can see v-html content don't have data-v attribute, but generate css have data-v attribute for svg.
I know this is expected behavior for vue-loader (https://github.com/vuejs/vue-loader/issues/359). And in this issue descendent selectors mentioned. But as you can see I use it in my css and it's not worked.
How can I style v-html content?

I am using vue-loader 15.9.1. The >>> solution did not work for me (no effect) whereas the /deep/method resulted in building errors...
Here is what worked instead:
.foo ::v-deep .bar { color: red; }

As stated in my answer here:
New version of vue-loader (from version 12.2.0) allows you to use "deep scoped" css. You need to use it that way:
<style scoped> now support "deep" selectors that can affect child
components using the >>> combinator:
.foo >>> .bar { color: red; } will be compiled into:
.foo[data-v-xxxxxxx] .bar { color: red; }
More informations on the release page of vue-loader

AS Sarumanatee said if the accepted answer doesn't work try:
.foo /deep/ .bar { color: red; }

Using /deep/ selector with SCSS didn't work for me but then I tried using ::v-deep selector
e.g
::v-deep a {
color: red;
}
See this answer

Related

Why do SCSS variables imported from another file doesn't work in Vue 3?

I have installed sass loader in my vue 3 project, but the issue is that I want to import variables from another file, but doesn't work
my schema is:
src
assets
scss
styles.scss
_variables.scss
styles.scss
#import url('./_variables.scss');
body{
font-family: 'Montserrat';
background-color: $primary-black;
}
.sidebar{
width: 250px;
height: 100vh;
max-height: 100vh;
background-color: $primary-black;
}
_variables.scss
$primary-black: #222222;
App.vue
Some HTML
<script>
import Sidebar from './components/Sidebar';
export default {
components: { Sidebar },
setup() {
},
}
</script>
<style lang="scss" scope>
#import url('./assets/scss/styles.scss');
</style>
And the issue is that in the browser the $primary-black variable fails, it appears background-color: $primary-black literally, I mean doesn't take de "#222222" color instead, but if I change the variable, and put it inside the styles.scss file, it works, so I'm not sure what could be the problem
Do not use the url function while importing, try the below
<style lang="scss" scope>
#import './assets/scss/styles.scss'
</style>

How do you nest all component scss in a selector in vue?

For example, if my app has two components with this SCSS
A component:
<style lang="scss" scoped>
.example {
color: red;
}
</style>
Another component:
<style lang="scss" scoped>
.another-example{
background: yellow;
}
</style>
Then I would like to have the SCSS from each component nested into one selector, so the resulting CSS will be
#my-app .example {
color: red;
}
#my-app .another-example{
background: yellow;
}
Is it possible to do this without going into every single component and nesting the SCSS inside the #my-app selector in every component?

How to disable Vuetify's style?

I want to parse markdown to html and use syntax highlighting.
My SFC is as follows:
<template>
<div v-html="html"></div>
</template>
<script>
import marked from 'marked'
import hljs from 'highlightjs';
export default {
name:"Article",
props:['md'],
computed:{
html(){
return marked(this.md)
}
},
created: function () {
marked.setOptions({
langPrefix: '',
highlight: function(code, lang) {
return hljs.highlightAuto(code, [lang]).value
}
})
},
}
</script>
<style src='highlightjs/styles/github-gist.css'></style>
The resulting code blocks are look like this:
This is Vuetify's style.
https://vuetifyjs.com/en/styles/content/#code
I want to disable or override it.
The following code does not work for code blocks:
<style scoped>
.v-application code {
background-color: unset !important;
color: unset !important;
box-shadow: unset !important;
}
.myclass {
color:red !important;
}
</style>
Result:
Vuetify has the following CSS specified for the code tags:
.v-application code {
background-color: #f5f5f5;
color: #bd4147;
box-shadow: 0 2px 1px -1px rgba(0,0,0,.2),
0 1px 1px 0 rgba(0,0,0,.14),
0 1px 3px 0 rgba(0,0,0,.12);
}
You can see this if you open developer tools and inspect a code tag on their website.
Either override those values to your own, or just set them all to unset or unset !important. For example:
.v-application code {
all: unset;
color: #eee
}
/* Or with increased specificity */
.v-application code.code--custom {
all: unset;
color: #eee
}
Actualy the style override you suffer from wouldn't be a problem if you just import your HighlightJS CSS directly after Vuetify in your main.js.
//main.js
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify';
import '<your_path>/highlight.min.css'
Consider also using a Vue Directive for global usage.
//main.js
Vue.directive('highlightjs', {
deep: true,
bind: function(el, binding) {
// highlight all targets
let targets = el.querySelectorAll('code')
targets.forEach((target) => {
// override this in case of binding
if (binding.value) {
target.textContent = binding.value
}
hljs.highlightBlock(target)
})
},
})
Then you can simply use it like this:
<pre v-highlightjs>
<code class="javascript">
// your code goes here //
</code>
</pre>
I made a JSFIDDLE for this, which is a modified version of a vue HighlightJS example by Chris Hager.
https://jsfiddle.net/b8jontzr/2/

How to do breakpoints in scss file with vuetify?

How to use media query breakpoints in my vuetify application but in scss file?
For example bootstrap enable me to do that in scss file:
#include media-breakpoint-up(sm) {
.custom-class {
display: block;
}
}
what is the equivalent in vuetify? I can't find any documention in vuetify website
You can do it in scss:
#import '~vuetify/src/styles/settings/_variables';
#media #{map-get($display-breakpoints, 'sm-and-down')} {
.custom-class {
display: block;
}
}
... and you're right there is very little docs regarding breakpoints within vuetify
I achieved this by attaching a class name corresponding to the breakpoint, which is available in the $vuetify.breakpoint object. Not a perfect solution, but I only needed to do it for once element in my app. Hope it helps!
Example:
<item :class="($vuetify.breakpoint.smAndDown) ? 'sm' : ''"></item>
...
<style scoped lang="scss">
#item{
right: 130px;
&.sm{
right: 35px;
}
}
</style>

How to use deep selector in scss in vue

How to use deep selector in scss in vue?
The code below not work.
<style lang="scss" scoped>
.a{
&>>>.b{
...
}
}
</style>
A deep selector like >>> in css but in scss inside vue single file component.
I had the same issue, and i eventually fix this using ::v-deep as stated here:
https://vue-loader.vuejs.org/guide/scoped-css.html#deep-selectors
<style lang="scss" scoped>
.v-input {
::v-deep .v-text-field__details {
min-height: 0;
margin: 0;
.v-messages {
min-height: 0;
}
}
}
</style>
From the vue docs:
"Some pre-processors, such as Sass, may not be able to parse >>> properly. In those cases you can use the /deep/ combinator instead - it's an alias for >>> and works exactly the same."
So try this:
<style lang="scss" scoped>
.a {
/deep/ .b {
...
}
}
</style>