Vue: adding style to app overrides styles of child components - vue.js

I have this simple page, designed with Vue and Tailwind:
App.vue:
<template>
<!-- <div class="bg-blue-500 flex flex-col h-screen min-h-screen " id="app">-->
<div id = "app" class = "bg-blue-500 flex flex-col h-screen min-h-screen app">
<Header/>
<main id ="app-main">
<p>app</p>
<router-link to="/home">Home</router-link>
<router-link to="/about">About</router-link>
</main>
<Footer/>
</div>
</template>
<script>
import Header from './components/Header.vue'
import Footer from './components/Footer.vue'
export default {
name: 'App',
components: {
Header, Footer
}
}
</script>
<style>
#app {
}
#app-main {
display: flex;
flex: 1 1 0%;
}
</style>
However if I edit #app style:
#app {
background-color: purple;
}
So as can be seen, when Tailwind is used, the styling behaves as expected: everything outside header and footer is blue, header and footer - their respective colors. However an attempt to set a color in the <style> tag, results in #app's background color overriding those of header and footer.
How do I fix it? How do people deal with it, when they don't use Tailwind?

If I understood you correctly, you are trying to change the color of the blue app region.
Notice the class bg-blue-500 on #app element? That's the class controlling the element's background color.
I can't check it but I bet renaming it to bh-purple-500 will color the background purple. You can find more default colors in the docs.
They way you're doing it overrides the styles of the child elements.

Related

Problems with scoped styles and deep styling in vue 3

Im having a lot of problems triying to style a child from parent in vue3.
In this case, i create a generic button with some css properties, and i try to customize this button from other component
Parent
<template>
<OwnButton
class="accept-button"
#ownButtonClicked="emit('accept')"
>
<slot>
ACCEPT
</slot>
</OwnButton>
</template>
<script setup>
import OwnButton from 'path/to/own-button.vue';
const emit = defineEmits(['accept']);
</script>
<style scoped>
.accept-button :deep(.own-button)
{
background-color : #4CAF50 !important;
outline-color : green !important;
}
.accept-button :deep(.own-button:hover)
{
background-color: green !important;
}
</style>
Child
<template>
<button
class="own-button"
type="button"
#click="emit('ownButtonClicked')"
v-on:keyup.enter="emit('ownButtonClicked')"
>
<slot>
</slot>
</button>
</template>
<script setup>
const emit = defineEmits
([
'ownButtonClicked'
]);
</script>
<style scoped>
.own-button
{
background-color : azure;
outline-color : lightblue;
color : black;
margin : 2px;
padding : 5px;
border-radius : 15px;
border : 0;
box-shadow : 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
outline-style : solid;
min-width : 100px;
max-width : 150px;
}
.own-button:hover
{
cursor: pointer;
}
</style>
I tried everything I could think of, including using :deep(button) in parent
This is a design limitation of Vue 3 when dealing with multi-root nodes
I wrote about this in my article Scoped styles and multi-root nodes don't work well together.
Understanding the issue
In Vue 3 we can finally have more than "one root node" components. That is great, but there is a design limitation when doing that. Imagine we have a child component:
<template>
<p class="my-p">First p</p>
<p class="my-p">Second p</p>
</template>
And a parent component:
<template>
<h1>My awesome component</h1>
<MyChildComponent />
</template>
<style scoped>
// There is no way to style the p tags of MyChildComponent
.my-p { color: red; }
:deep(.my-p) { color: red; }
</style>
There is no way from the scoped styling of the multi-root parent component to style the child component's p tags.
So in short, a multi-root component, can't target multi-root child component's styles with scoped styles.
Solutions
👉 💡 The best way to fix that would be to wrap the parent or child component (or both) so we have only one root element.
But if you absolutely need both to have multi-root nodes, you can:
Use a non-scoped style
<style>
.my-p { color: red; }
</style>
Use CSS Modules
<template>
<h1>My awesome component</h1>
<MyChildComponent :class="$style.trick" />
</template>
<style module>
.trick {
color: red;
}
</style>
Since we are specifying a class here, then the multi-root child component has to explicitly specify the attribute fallthrough behavior.
If you want my opinion, unless you absolutely need a multi-root node component, go with a single root node and don't deal with this design limitation at all.
I think it is related to where you apply the main class.
Try to put a wrapper around like that:
<template>
<div class="accept-button">
<OwnButton
#ownButtonClicked="emit('accept')"
>
<slot>
ACCEPT
</slot>
</OwnButton>
</div>
</template>
<script setup>
import OwnButton from './Comp.vue';
const emit = defineEmits(['accept']);
</script>
<style scoped>
.accept-button :deep(.own-button)
{
background-color : yellow !important;
outline-color : green !important;
}
.accept-button :deep(.own-button:hover)
{
background-color: green !important;
}
</style>
Here is the example above.

How do I make NuxtLink ignore css animation?

I have page with background-color animated. I'm trying to navigate to another page using NuxtLink, but it doesn't render another page until css animation on the current page finishes. Is there a way for a NuxtLink to ignore animations?
Page with animation
<template>
<div class="animated">
<h1>MAIN</h1>
</div>
</template>
<script>
export default {
name: "IndexPage",
};
</script>
<style scoped>
.animated {
background-color: rgba(0, 0, 0, 1);
animation-duration: 5s;
animation-fill-mode: forwards;
animation-name: anim;
}
#keyframes anim {
from {
background-color: black;
}
to {
background-color: red;
}
}
</style>
Layout with NuxtLinks
<template>
<div>
<nav>
<NuxtLink to="/">Main</NuxtLink>
<NuxtLink to="/foo">Foo</NuxtLink>
<NuxtLink to="/bar">Bar</NuxtLink>
</nav>
<Nuxt />
</div>
</template>
Another page without animation
<template>
<h1>FOO</h1>
</template>
When I try to navigate from Main to Foo page, it transitions only after animation in main finishes. I would like it to transition to another page regardless of css.
Example: https://codesandbox.io/s/heuristic-kate-k4t77r
I got it working by wrapping the animated page inside a div. It might be colliding with nuxt transitions, I'm not sure but now it works.
<template>
<div>
<div class="animated">
<h1>MAIN</h1>
</div>
</div>
</template>

Nuxt: css of error.vue appears in page rendering

I am new to Nuxt.
I have a page
pages/page1.vue
<template>
<h1 class="title">Page</h1>
</template>
<style>
.title {
font-size: 16px;
}
</style>
Then, under layouts I have an error.vue
layouts/error.vue
<template>
<h1 class="title">Error Page</h1>
</template>
<style>
.title {
color: red;
font-size: 18px;
}
</style>
What I found is that when page1 is rendered, the title appears in Red. I checked the inspect elements and found that the CSS of error as well as of page 1 is applied.
I do not have a default.vue in the layouts directory.
As mentioned this is my first project in Nuxt (or vue) and want to understand how to ensure that CSS of a page are applied on that page only. This is in development mode (npm run dev). Thanks
The issue is CSS without scoped attribute renders at application level. You should use scoped attribute in styles tag as
layouts/error.vue
<template>
<h1 class="title">Error Page</h1>
</template>
<style scoped>
.title {
color: red;
font-size: 18px;
}
</style>
**When a <style> tag has the scoped attribute, its CSS will apply to elements of the current component only otherwise consider global style.

How to change Vuetify v-icon color in css

Vuetify v-icon usually takes its color with a class. In my case, I am trying to change its color with a css class menu-icon when my router link is active.
<v-btn icon class="menu-btn">
<router-link to="/client/dashboard">
<v-icon class="menu-icon">
mdi-gauge-full
</v-icon>
<div class="menu-titles">Dashboard</div>
</router-link>
</v-btn>
.router-link-active .menu-icon {
color: #2F80ED ;
}
The problem is v-icon does not seems to accept css color attribute. Is there a way to change it with css ?
<v-icon> uses the value of its CSS color property and maps it into the fill property of it's SVG children (using fill="currentColor").
So you only need to set the color CSS value on .v-icon, and it will work:
Simple example:
<v-icon large>mdi-domain</v-icon>
In CSS:
i.v-icon.v-icon {
color: red;
}
Working example:
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
vuetify: new Vuetify(),
})
i.v-icon.v-icon {
color: red;
}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-content>
<v-icon>mdi-domain</v-icon>
</v-content>
</v-app>
</div>
I advise against using !important.
By default, Vuetify sets the color of icons using a 2 × class specificity (i.e: .theme--light.v-icon), so we need to use something slightly higher i.v-icon.v-icon ( 1 × el + 2 × class ).
Obviously, if you want to do it inline you can always go with the anti-pattern of inline style:
<v-icon large style="color: red;">mdi-domain</v-icon>
Like any anti-pattern, it's not recommended. But it's possible.
Maybe this can help
<v-icon large color="green darken-2">mdi-domain</v-icon>
Or if you want to change color using internal css, you can add a style tag like this at the end.
<style lang="scss" >
.classname {
color: red !important;
}
</style>
In my case, didn't work putting the color's name, but it worked putting the hexadecimal value:
<v-icon color="#933">mdi-close</v-icon>
Despite the fact that in the documentation of the Vuetify icons, you find that it works by putting the names. But is required put v-app tag in vue template. Let it start this way:
<template>
<v-app>
<v-icon color="red">mdi-close</v-icon>
</v-app>
</template>
You should add to your css file:
.theme--light.v-icon,
.theme--dark.v-icon {
color: inherit !important;
}

Navbar transparent in buefy

I am creating a landpaging and I am facing some style difficulties due to lack of practice.
I want to modify the backgroud of the navbar, so I wanted to make the background transparent so that the bottom of the page appears. How can I do this?
enter image description here
<template>
<div class="Shellhub-LP-1280">
<div class="textura Nuvem">
<b-navbar>
<template slot="brand">
<b-navbar-item tag="router-link" :to="{ path: '/' }" transparent="true">
<img
src="https://raw.githubusercontent.com/buefy/buefy/dev/static/img/buefy-logo.png"
alt="Lightweight UI components for Vue.js based on Bulma"
>
<!-- <img src="#/static/logo-inverted.png"> -->
</b-navbar-item>
</template>
...
</b-navbar>
</div>
</div>
</template>
<style>
.Shellhub-LP-1280 {
/* width: 100%; */
height: 2283px;
background-color: #333640;
}
.textura {
/* width: 100%; */
height: 771px;
}
.Nuvem {
width: 100%;
height: 755px;
object-fit: contain;
opacity: 0.9;
float: right;
background: url('../static/nuvem.png');
background-repeat: no-repeat;
background-position: right;
}
Thanks
buefy navbar API:
https://buefy.org/documentation/navbar/#api-view
Passing this props:
<b-navbar :fixed-top="true" :transparent="true" >
Vue docs - components props (recommend to read):
https://v2.vuejs.org/v2/guide/components-props.html
transparent "bug":
Open github issue:
BUG: navbar is-transparent not working .
IMPORTANT: transparent affect navbar items (Not the navbar wrapper himself).
Remove any hover or active background from the navbar items
So add simple CSS styling:
nav.navbar.is-fixed-top {
background: transparent;
}
body top padding issue
I won't find a way to remove body top padding. I added this style:
body{
padding-top: 0px!important;
}
Basic example:
const app = new Vue()
app.$mount('#app')
img.responsive_img{
width: 100%;
height: auto;
}
body{
padding-top: 0px!important;
}
/* change navbar background color */
nav.navbar.is-fixed-top {
background: transparent;
}
<link href="https://unpkg.com/buefy/dist/buefy.min.css" rel="stylesheet"/>
<div id="app">
<b-navbar class="is-link" :fixed-top="true" :transparent="true">
<template slot="brand">
<b-navbar-item tag="router-link" :to="{ path: '/' }">
<img
src="https://raw.githubusercontent.com/buefy/buefy/dev/static/img/buefy-logo.png"
alt="Lightweight UI components for Vue.js based on Bulma"
>
</b-navbar-item>
</template>
<template slot="start">
<b-navbar-item href="#">
Home
</b-navbar-item>
<b-navbar-item href="#">
Documentation
</b-navbar-item>
<b-navbar-dropdown label="Info">
<b-navbar-item href="#">
About
</b-navbar-item>
<b-navbar-item href="#">
Contact
</b-navbar-item>
</b-navbar-dropdown>
</template>
<template slot="end">
<b-navbar-item tag="div">
<div class="buttons">
<a class="button is-primary">
<strong>Sign up</strong>
</a>
<a class="button is-light">
Log in
</a>
</div>
</b-navbar-item>
</template>
</b-navbar>
<header style="min-height: 200vh;">
<img class="responsive_img" src="https://picsum.photos/2000/600"/>
</header>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/buefy/dist/buefy.min.js"></script>
Change navbar background color on scroll
only by custom code
See this codepen (I added a class on scroll):
https://codepen.io/ezra_siton/pen/jOPZgmR
Change the background color on scroll her:
nav.navbar.is-fixed-top.isActive{
transition: background-color 0.5s ease;
background: red; /* change color on scroll */
}
Change navbar links color to white (For dark hero) - add "is-link" modifier:
https://bulma.io/documentation/components/navbar/#colors
<b-navbar class="is-link" :fixed-top="true" :transparent="true" >
Remove hover/active
:transparent="true"
Remove any hover or active background from the navbar items.