I'm currently using vue-router to send us to an about page like so:
# #/views/About
<template>
<p>About Vue...</p>
</template>
<script>
[...]
</script>
<style>
</style>
The way routes are rendered are like so:
# #/App.vue
<template>
<Header />
<router-view>
</template>
<script>
import ...
</script>
<style>
header {
background: black;
}
</style>
Question:
How would I go about changing the header background color ONLY when I am on the About.vue (if i go to other routes like / or /contact header should stay the same)?
Thank you in advance for the help
Use a watcher or a computed property to watch your this.$route then conditionally apply a class or style based on if you're currently on the /about route. For example ..
# #/App.vue
<template>
<Header :class="[altBackground ? 'header-red' : 'header-black']" />
<router-view>
</template>
<script>
import ...
computed: {
altBackground() {
const path = this.$route.path.split('/')
return path[path.length-1].toLowerCase() === 'about'
}
}
</script>
<style>
.header-black {
color: black;
}
.header-red {
color: red;
}
</style>
Related
I want to style inline SVG, but NuxtJS (or better say WebPack) doesn't include this styling into output CSS:
<template>
<header>
<NuxtLink to="/" v-html="logoIco" class="logo"></NuxtLink>
</header>
</template>
<script>
export default {
name: 'HeaderComponent',
computed: {
logoIco() {
return require(`assets/images/logo.svg?raw`);
},
},
};
</script>
<style scoped lang="scss">
header {
.logo {
background: red; // this style included in result CSS
svg {
background: yellow; // and this NOT
}
}
}
</style>
WebPack doesn't see any SVG during build and doesn't include header .logo svg rule in resulting CSS.
How this can be done?
I've found an idea here: https://github.com/nuxt-community/svg-module/issues/72
This code works as expected:
<template>
<header>
<NuxtLink to="/" v-html="logoIco" class="logo">
<component :is="require(`assets/images/logo.svg?inline`)"></component>
</NuxtLink>
</header>
</template>
<script>
export default {
name: 'HeaderComponent',
};
</script>
<style scoped lang="scss">
header {
.logo {
background: red; // this style included in result CSS
svg {
background: yellow; // and this now also included
}
}
}
</style>
Please see this minimum example
I have a Child.vue and Parent.vue which look like this
<!-- Child.vue -->
<template>
<div :class="'bg-gray text-white'">I'm Child</div>
</template>
<template>
<Child class="p-4" />
</template>
<script>
import Child from "./Child.vue";
export default {
components: {
Child,
},
};
</script>
<style>
.p-4 {
padding: 16px;
}
.bg-gray {
background: gray;
}
.text-white {
color: white;
}
</style>
The final class name for Child.vue wrapper element will be bg-gray text-white p-4, class names are all merged.
However, I would like to create a v-class directive and make my API looks like this
<!-- Child.vue -->
<template>
<div v-class="'bg-gray text-white'">I'm Child</div>
</template>
<script>
export default {
directives: {
class: {
inserted(el, binding) {
const css = String.raw; // Not doing anything right now.
el.className = css`
${binding.value}
`;
},
},
},
};
</script>
And Parent.vue stays the same.
Now the final merged class name is bg-gray text-white, p-4 is missing!
How can I preserve p-4 just like I'm using regular :class prop?
My use case is I want to use the tagged template literal function in my Vue template.
However, Vue doesn't support template literal function in the template, the compiler will yell!
For example
<div :class="css`text`"></div>
Try out to push the value to the class list :
el.classList.add( css`
${binding.value}
`);
I am using Gridsome for the first time. I am just trying to setup the layout of my website - I don't have any API connected or anything, just trying to output raw HTML. I have a SkipToContent component and a Header component. Both are outputting the contents of the Header component, and I'm rather confused. I've tried restarting the local server and general debugging stuff like making sure the files are all saved. Below are the files:
Header.vue
<template>
<header class="header">
<strong>
<g-link to="/">{{ $static.metadata.siteName }}</g-link>
</strong>
<nav class="nav">
<g-link class="nav__link" to="/">Home</g-link>
<g-link class="nav__link" to="/about/">About</g-link>
<g-link class="nav__link" to="/web/">Web Development</g-link>
<g-link class="nav__link" to="/photography/">Photography</g-link>
</nav>
</header>
</template>
<script lang="ts">
import Vue from "vue";
export default class Header extends Vue {}
</script>
<static-query>
query {
metadata {
siteName
}
}
</static-query>
<style lang="scss">
#use '../styles/common' as *;
</style>
SkipToContent.vue
<template>
Skip to content
</template>
<script lang="ts">
import Vue from 'vue';
export default class SkipToContent extends Vue {}
</script>
<static-query>
query {
metadata {
siteName
}
}
</static-query>
<style lang="scss">
#use '../styles/common' as *;
.skip-to-content {
&__link {
position: fixed;
left: 50%;
transform: translate(-50%, -200%);
transition: transform 0.15s ease;
background: $primary;
&:focus {
transform: translate(-50%, 50%);
}
}
}
</style>
Default.vue
<template>
<div class="layout">
<SkipToContent />
<Header />
<main id="main-content">
<slot />
</main>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import SkipToContent from "~/components/SkipToContent.vue";
import Header from "~/components/Header.vue";
import { Component } from "vue-property-decorator";
#Component({
components: {
Header,
SkipToContent,
}
})
export default class App extends Vue {
};
</script>
<static-query>
query {
metadata {
siteName
}
}
</static-query>
<style lang="scss">
#use '../styles/common' as *;
#import url("https://rsms.me/inter/inter.css");
html {
font-family: "Inter", sans-serif;
}
#supports (font-variation-settings: normal) {
html {
font-family: "Inter var", sans-serif;
}
}
</style>
HTML Output:
I feel like I'm either doing something very obvious incorrectly, or this is some sort of issue with using TypeScript in Gridsome?
Thanks for any suggestions :)
Some of my single-file components need to take hover color from props.
My solution is that i set css variables in the following way (the main part is in the mounted(){...})
<template>
<div class="btnWrapper" ref="btnWrapper">...</div>
</template>
...
...
props() {
color1: {type: String, default: 'blue'},
},
mounted () {
this.$refs.btnWrapper.style.setProperty('--wrapHoverColor', this.color1)
}
...
...
<style scoped>
.btnWrapper {
--wrapHoverColor: pink;
}
.btnWrapper:hover {
background-color: var(--wrapHoverColor) !important;
}
</style>
This solution seems kind of woowoo.
But maybe there is no better way with pseudo elements, which are hard to control from js.
Do you guys ever take pseudo element's properties from props in vue components?
You have two different ways to do this.
1 - CSS Variables
As you already know, you can create CSS variables from what you want to port from JS to CSS and put them to your root element :style attr on your components created hooks, and then use them inside your CSS codes with var(--x).
<template>
<button :style="style"> Button </button>
</template>
<script>
export default {
props: ['color', 'hovercolor'],
data() {
return {
style: {
'--color': this.color,
'--hovercolor': this.hovercolor,
},
};
}
}
</script>
<style scoped>
button {
background: var(--color);
}
button:hover {
background: var(--hovercolor);
}
</style>
2 - Vue Component Style
vue-component-style is a tiny (~1kb gzipped) mixin to do this internally. When you active that mixin, you can write your entire style section inside of your component object with full access to the component context.
<template>
<button class="$style.button"> Button </button>
</template>
<script>
export default {
props: ['color', 'hovercolor'],
style({ className }) {
return [
className('button', {
background: this.color,
'&:hover': {
background: this.hovercolor,
},
});
];
}
}
</script>
UPDATE | found the reason to this:
If you put the <router-view> in a <main> tag this will happen.
Question
I'm not sure if that's how it supposed to work.
But the component isn't taking 100% of the page width. Do you always have to specify the width of the component (routed page) manually or I'm doing something wrong?
I'm using Vuetify.js library (installed via npm)
I'm expecting this element <p>some text here</p> on the page Home.vue to take up 100% of the page's width (as normal), but it's not:
CODE:
App.vue | router => Home.vue
<!-- toolbar and drawer are here -->
<main>
<router-view></router-view>
</main>
</v-app>
</template>
<script>
export default {
name: 'app',
data () {
return {
drawer: false
}
}
}
</script>
Home.vue page
<template>
<div>
<p>some text here</p>
</div>
</template>
<script>
export default {
name: 'home',
data () {
return {
snackbar: true
}
}
}
</script>
It is a css issue, in Home.vue explicitly set the div width to be 100% should work:
<css scoped>
div {
width: 100%;
}
</css>