I'm trying to change the elevation of my v-cards in vuetify in my index.vue page but the changes dont show up, right now the code for my card reads: <v-card class="cards" elevation="0" shaped> but I tried it with class="elevation-0" as well. It doesn't work with any elevation but if I e.g. use the attribute: ``` the changes show up.
In my other pages the elevation attribute works (in my _slug.vue page), just in the index.vue page it doesn't. I also tried to change move the code of the cards to an own component but it doesn't work as well.
The Component in my index.vue file:
<template>
<NuxtLink :to="'/' + Link">
/* This is the card I'm talking about */
<v-card class="cards" elevation="0" shaped>
<img class="thumbnail" :src="Image" />
<h3 class="video-title">{{ Title }}</h3>
<h3 class="video-type">Most {{ Name }}:</h3>
</v-card>
</NuxtLink>
</template>
<script>
export default {
name: "ThumbnailCard",
props: {
Image: String,
Title: String,
Link: String,
Name: String,
},
};
</script>
<style scoped>
.cards {
margin-top: 15vh;
margin-left: 1vw;
margin-right: 1vw;
height: 30vh;
text-align: center;
}
.thumbnail {
width: 100%;
height: 30vh;
}
.video-type {
position: absolute;
top: 0;
left: 0;
right: 0;
margin-top: 9vh;
}
.video-title {
position: absolute;
top: 0;
left: 0;
right: 0;
margin-top: 18vh;
}
#media only screen and (max-width: 599px) {
.cards {
margin-top: 2vh;
margin-bottom: 2vh;
margin-left: 15vw;
margin-right: 15vw;
height: 14.5vh;
}
.thumbnail {
height: 14.5vh;
}
.video-type {
margin-top: 4vh;
}
.video-title {
margin-top: 8vh;
}
}
</style>
The whole code for my index.vue:
<template id="main">
<div>
<div id="title-section">
<h1 id="title">Title</h1>
<h2 id="description">This Site is awesome, have a look</h2>
</div>
<v-container id="content-wrapper">
<v-row no-gutters>
<v-col cols="12" sm="4">
<ThumbnailCard
:Image="recentImage"
:Title="recentTitle"
:Link="recentLink"
Name="Recent"
/>
</v-col>
<v-col cols="12" sm="4">
<ThumbnailCard
:Image="popularImage"
:Title="popularTitle"
:Link="popularLink"
Name="Popular"
/>
</v-col>
<v-col cols="12" sm="4">
<ThumbnailCard
:Image="relevantImage"
:Title="relevantTitle"
:Link="relevantLink"
Name="Recent"
/>
</v-col>
</v-row>
</v-container>
</div>
</template>
<script>
import ThumbnailCard from "#/components/global/ThumbnailCard";
export default {
name: "index",
components: {
ThumbnailCard: ThumbnailCard,
},
async asyncData({ $content, params }) {
const articles = await $content("articles")
.only(["date", "slug", "title", "img"])
.fetch();
const datesArr = articles.map((a) => {
return new Date(a.date).getTime() / 1000;
});
const recentTitle = articles[datesArr.indexOf(Math.min(...datesArr))].title;
const recentLink = articles[datesArr.indexOf(Math.min(...datesArr))].slug;
const recentImage = articles[datesArr.indexOf(Math.min(...datesArr))].img;
const popularTitle = articles[0].title;
const popularLink = articles[0].slug;
const popularImage = articles[0].img;
const relevantTitle = articles[0].title;
const relevantLink = articles[0].slug;
const relevantImage = articles[0].img;
return {
recentTitle,
recentLink,
recentImage,
popularTitle,
popularLink,
popularImage,
relevantTitle,
relevantLink,
relevantImage,
};
},
};
</script>
<style>
html {
overflow-y: auto;
}
::-webkit-scrollbar {
width: 5px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background: #888;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
#title-section {
background: black;
width: 100%;
height: 40vh;
text-align: center;
}
#title {
color: white;
font-size: 4rem;
}
#description {
color: white;
}
#content-wrapper {
height: 60vh;
width: 100%;
}
</style>
For anyone having the same problem: I forgot the <v-app> component which somehow resulted in the elevation attribute not working
the flat attribute works well to remove elevation from most vuetify components
Related
I am using nuxt and bootstrap to build a custom hover dropdown menu for navigation. The issue I have is that my navigation submenu NuxtLinks are refreshing the entire page instead of smoothly changing the app content in my Nuxt block. The nav bar is dynamically generated in the default.vue layout and uses a b-dropdown-hover component where the NuxtLink is wrapped around that content. Why does the page do a full refresh for those links/anchors but my b-navbar-brand image does a smooth transition? I apologize, I am very new to Nuxt. This video # ~1:35:00 demonstrates what I'm trying to do.
components/BDropdownHoverRight.vue
<template>
<nuxt-link :to="aTo">
<div class="ddr-top" #mouseover="onOver1($event.target)" #mouseleave="onLeave1($event.target)">
<b-dropdown ref="dropdown_ddr" :text="cText" class="m-md-2 ddr">
<slot></slot>
</b-dropdown>
</div>
</nuxt-link>
</template>
<script>
export default {
name: 'BDropdownHoverRight',
props: {
cText: {
type: String,
},
aTo: {
type: String,
},
},
methods: {
onOver1(t) {
if (t.nodeName === 'DIV') {
console.log(t)
console.log(t.nodeName)
let num_child_nodes = 0
try {
if (t.querySelectorAll(':scope > ul')[0].getElementsByTagName('div').length >= 0) {
num_child_nodes = t.querySelectorAll(':scope > ul')[0].getElementsByTagName('div').length
}
} catch (e) {
if (t.querySelectorAll(':scope > div > ul')[0].getElementsByTagName('div').length >= 0) {
num_child_nodes = t.querySelectorAll(':scope > div > ul')[0].getElementsByTagName('div').length
}
}
if (num_child_nodes > 0) {
try {
t.querySelectorAll(':scope > div > ul')[0].style.display = 'block'
} catch (e) {
try {
t.querySelectorAll(':scope > ul')[0].style.display = 'block'
} catch (e) {}
}
}
}
},
onLeave1(t) {
try {
t.querySelectorAll(':scope > div > ul')[0].style.display = 'none'
} catch (e) {
try {
t.querySelectorAll(':scope > ul')[0].style.display = 'none'
} catch (e) {}
}
},
},
}
</script>
layouts/default.vue
<template>
<div>
<b-navbar id="top-nav-bar" toggleable="lg" type="light" sticky>
<b-navbar-brand to="/">
<Rabbit id="tl-logo" />
</b-navbar-brand>
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
<b-collapse id="nav-collapse" is-nav>
<b-navbar-nav>
<template v-for="dir in navtop_dd">
<b-dropdown-hover
:key="dir.id"
:c-text="dir.name"
:a-to="dir.hasOwnProperty('ato') ? dir.ato : '/nolink'"
>
<template v-if="'submenus' in dir && dir.submenus.length > 0">
<template v-for="dir1 in dir.submenus">
<b-dropdown-hover-right
:key="dir1.id"
:c-text="dir1.name"
:a-to="dir1.hasOwnProperty('ato') ? dir1.ato : '/nolink'"
>
<template v-if="'submenus' in dir1 && dir1.submenus.length > 0">
<template v-for="dir2 in dir1.submenus">
<b-dropdown-hover-right
:key="dir2.id"
:c-text="dir2.name"
:a-to="dir2.hasOwnProperty('ato') ? dir2.ato : '/nolink'"
>
</b-dropdown-hover-right>
</template>
</template>
</b-dropdown-hover-right>
</template>
</template>
</b-dropdown-hover>
</template>
</b-navbar-nav>
<!-- Right aligned nav items -->
<b-navbar-nav class="ml-auto">
<b-nav-form>
<b-form-input size="sm" class="mr-sm-2" placeholder="Search"></b-form-input>
<b-button size="sm" class="my-2 my-sm-0" type="submit">Search</b-button>
</b-nav-form>
<b-nav-item-dropdown right>
<!-- Using 'button-content' slot -->
<template #button-content>
<b-img src="../assets/imgs/account-circle.svg" style="height: 35px"> </b-img>
<!-- <em>User</em> -->
</template>
<b-dropdown-item href="#">Profile</b-dropdown-item>
<b-dropdown-item href="#">Sign Out</b-dropdown-item>
</b-nav-item-dropdown>
</b-navbar-nav>
</b-collapse>
</b-navbar>
<b-container id="app-content">
<Nuxt />
</b-container>
<div id="footer">
<div style="height: 100%; padding: 5px">© 2021</div>
</div>
</div>
</template>
<script>
import BDropdownHover from '#/components/BDropdownHover'
import BDropdownHoverRight from '#/components/BDropdownHoverRight'
export default {
components: {
BDropdownHover,
BDropdownHoverRight,
},
data() {
return {
navtop_dd: [
{
id: 1,
name: 'Transactions',
ato: '/transactions',
submenus: [
{
id: '1a',
name: 'Sales Orders',
ato: '/transactions/salesorders',
submenus: [
{
id: '1b',
name: 'New',
},
{
id: '2b',
name: 'List',
},
],
},
{
id: '2a',
name: 'Item Fulfillments',
ato: '/transactions/itemfulfillments',
submenus: [
{
id: '1b',
name: 'New',
},
{
id: '2b',
name: 'List',
},
],
},
],
},
{
id: 2,
name: 'Inventory',
},
{
id: 3,
name: 'Reports',
},
{
id: 4,
name: 'Setup',
},
{
id: 5,
name: 'Support',
},
],
}
},
mounted() {
var x = document.querySelectorAll('.b-dropdown.navtop-dd')
for (var i = 0; i < x.length; i++) {
if (x[i].querySelectorAll(':scope > ul')[0].getElementsByTagName('div').length == 0) {
var btn = x[i].querySelectorAll(':scope > .btn')[0]
btn.classList += ' no-content-after'
}
}
var x = document.querySelectorAll('.b-dropdown.ddr')
for (var i = 0; i < x.length; i++) {
if (x[i].querySelectorAll(':scope > ul')[0].getElementsByTagName('div').length == 0) {
var btn = x[i].querySelectorAll(':scope > .btn')[0]
btn.classList += ' no-content-after'
}
}
},
}
</script>
<style>
#top-nav-bar {
border-bottom: 1px solid green;
}
#tl-logo {
height: 40px;
margin: 5px;
}
#footer {
height: 40px;
color: black;
border-top: 1px solid green;
margin: auto;
text-align: center;
display: flex;
align-items: center;
justify-content: space-around;
}
.navtop-dd button {
background: none !important;
color: #6c757d !important;
border: none !important;
}
#app-content {
margin: 20px auto;
}
.ddr > button::after {
display: inline-block;
margin-left: 0.555em;
right: 0px;
content: "";
border-top: 0.25em solid transparent;
border-right: 0.3em solid transparent;
border-bottom: 0.25em solid transparent;
border-left: 0.35em solid;
vertical-align: 0.075em;
}
.b-dropdown {
width: 100%;
}
.ddr > button {
text-align: left;
}
.no-content-after::after {
content: none !important;
}
.ddr > ul {
top: -1.2rem;
left: calc(100% - 0.5rem);
}
.dropdown-menu {
min-width: 0 !important;
}
.dropdown-item {
color: #6C757D;
}
.ddr-top:hover {
background-color: #e4ffda;
}
a:hover {
text-decoration: none !important;
}
</style>
There is a LOT of irrelevant code here. I took the time to format it properly. Please make the effort yourself next time (to format and input interesting bits only).
Also, the answer on how to fix the issue was actually given in the video itself. The video is talking about the differences between a and nuxt-link tags.
Which relates to this part of Bootstrap's Vue documentation where you can see that
[to] prop: Denotes the target route of the link. When clicked, the value of the to prop will be passed to router.push() internally, so the value can be either a string or a Location descriptor object
So, you should use something like this
<template>
<b-dropdown>
<template #button-content>
Custom <strong>Content</strong> with <em>HTML</em> via Slot
</template>
<b-dropdown-item to="/test">Go to test page via Vue-router</b-dropdown-item>
</b-dropdown>
</template>
I also saw that your code is rather different from the video. You should not use querySelector, you don't have to import Nuxt components neither and you have several ESlint warning/errors.
I do recommend trying to focus on a single part of learning and not mixing all of them. It's fine to want to go a bit further, but be careful of not being lost with too much abstraction while you do learn a lot of new concepts (Vue/Nuxt).
On a side note, if you want to continue learning Nuxt, you can check this: https://masteringnuxt.com/ (created by a Nuxt ambassador and other well known people in the Vue ecosystem)
Have fun creating projects with Nuxt!
the code below animates the element you click on, but I want it to smoothly decrease the height to zero as well. Unfortunately, the height does not change, but everything works with opacity.
height: 0 !improtant; //does not help to solve the problem
<template>
<transition-group name="msgAnimation" tag="div">
<div v-for="(obj, i) in messages" :key="obj.key" class="wrapper">
<div class="wrapper__block" #click="messages.splice(i, 1)">
{{ obj.msg }}
</div>
</div>
</transition-group>
</template>
<style lang="css">
.msgAnimation-enter-active,
.msgAnimation-leave-active {
transition: all 5s;
}
.msgAnimation-enter,
.msgAnimation-leave-to {
height: 0;
opacity: 0;
}
.wrapper {
width: 100%;
height: 9vmin;
}
.wrapper__block {
background: green;
height: 9vmin;
width: 100%;
}
</style>
<script>
export default {
name: "HelloWorld",
data() {
return {
totalAmount: 0,
messages: [{ key: 0, msg: "Are u hacker" }],
};
},
};
</script>
Your CSS rules was declared after your animation
const example = {
data() {
return {
totalAmount: 0,
messages: [{
key: 0,
msg: "Are u hacker"
},
{
key: 1,
msg: "Are u hacker"
}
],
};
},
};
const app = new Vue(example);
app.$mount("#app");
.msgAnimation-enter-active,
.msgAnimation-leave-active {
transition: all 5s;
}
.wrapper {
width: 100%;
height: 9vmin;
overflow:hidden;
}
.wrapper__block {
background: green;
width: 100%;
}
.msgAnimation-enter,
.msgAnimation-leave-to {
opacity: 0;
height: 0;
}
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<div id="app">
<transition-group name="msgAnimation" tag="div">
<div v-for="(obj, i) in messages" :key="obj.key" class="wrapper">
<div class="wrapper__block" #click="messages.splice(i, 1)">
{{ obj.msg }}
</div>
</div>
</transition-group>
</div>
You're not limiting overflow of .wrapper, and you have a height specified in .wrapper__block. Thus, even if .wrapper goes smoothly to 0, its child will not.
Setting height: 100%; on .wrapper__block, or setting overflow: hidden on .wrapper should do the trick.
<template>
<transition-group name="msgAnimation" tag="div">
<div v-for="(obj, i) in messages" :key="obj.key" class="wrapper">
<div class="wrapper__block" #click="messages.splice(i, 1)">
{{ obj.msg }}
</div>
</div>
</transition-group>
</template>
<style lang="css">
.msgAnimation-enter-active,
.msgAnimation-leave-active {
transition: all 5s;
}
.msgAnimation-enter,
.msgAnimation-leave-to {
height: 0;
opacity: 0;
}
.wrapper {
width: 100%;
height: 9vmin;
}
.wrapper__block {
background: green;
height: 100%;
width: 100%;
}
</style>
<script>
export default {
name: "HelloWorld",
data() {
return {
totalAmount: 0,
messages: [{ key: 0, msg: "Are u hacker" }],
};
},
};
</script>
Alternatively, if you don't mind distortion during the animation, it's a lot more performant to animate transform: scaleY(0), as transform and opacity are applied at the Composition step in CSS, you prevent a lot of in-between style calculations, making your app noticeably faster whn you have several thousand messages.
Being new to Vue, came across the following use-case. I have an accordion component that is reused across the application. The accordion simply hides and reveals anything wrapped inside it.
How can I enable closing any other open instance when I open an instance? e.g if prototype accordion is open, then functions and objects accordion is clicked, prototype accordion should close.
const vue = Vue.createApp({});
vue.component('accordion', {
data() {
return {
open: false,
}
},
methods: {
toggle() {
this.open = !this.open;
},
},
template: `
<div class="accord">
<p #click="toggle" class="accord-header">Click me to open and close!</p>
<div v-if="open" class="accord-body">
<slot></slot>
</div>
</div>
`,
})
vue.mount('#main-app');
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
#main-app {
width: 50%;
margin: 0 auto;
}
.accord {
padding: 4px;
cursor: pointer;
}
.accord-header {
text-align: center;
padding: 4px 0;
}
.accord-body {
background-color: #eee;
padding: 8px;
}
<script src="https://unpkg.com/vue#next"></script>
<div id="main-app">
<accordion>
<p class="accord-text">Javascript Proptotypes and inheritance</p>
</accordion>
<accordion>
<p class="accord-text">Scopes and Closures</p>
</accordion>
<accordion>
<p class="accord-text">Functions and Objects</p>
</accordion>
</div>
You can change open to be a prop, then you can do something like activeAccordianId: 1 in the parent and have the prop be
<accordian :open="activeAccordianId === 1" />
<accordian :open="activeAccordianId === 2" />
...
I've read through innumerable posts about how to do this with jquery, but Vue.js jealously owns and manages the dom, so I will need a solution that uses standard Vue.js components or libraries.
Thus far, I've located several examples that are what I'd call 'button-event-driven' solutions, but I will need to programmatically handle open and close of the modal.
Problem / Design Requirement: When a public user attempts to interact with a tempting button or other function on my application, and they are not yet logged in, I wish to programmatically launch a modal dialogue to then ask them to log in.
Once successfully, I'll need to programmatically close the same dialogue modal. Or, of course, they can choose to cancel and continue browsing as a public user without the ability to do those functions.
Other Helpful Information: I'm using bootstrap 4.4.1
You can use a watch property. If a user is not logged in as login=false then the modal shows.
// register modal component
Vue.component("modal", {
template: "#modal-template"
});
// start app
new Vue({
el: "#app",
data: {
showModal: false,
login: null
},
created() {
this.login = false;
},
watch: {
"login": function(val) {
this.showModal = !val;
}
}
});
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: table;
transition: opacity 0.3s ease;
}
.modal-wrapper {
display: table-cell;
vertical-align: middle;
}
.modal-container {
width: 300px;
margin: 0px auto;
padding: 20px 30px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
transition: all 0.3s ease;
font-family: Helvetica, Arial, sans-serif;
}
.modal-header h3 {
margin-top: 0;
color: #42b983;
}
.modal-body {
margin: 20px 0;
}
.modal-default-button {
float: right;
}
/*
* The following styles are auto-applied to elements with
* transition="modal" when their visibility is toggled
* by Vue.js.
*
* You can easily play with the modal transition by editing
* these styles.
*/
.modal-enter {
opacity: 0;
}
.modal-leave-active {
opacity: 0;
}
.modal-enter .modal-container,
.modal-leave-active .modal-container {
-webkit-transform: scale(1.1);
transform: scale(1.1);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Modal Component</title>
<link rel="stylesheet" type="text/css" href="/style.css" />
<!-- template for the modal component -->
<script type="text/x-template" id="modal-template">
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
default body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
default footer
<button class="modal-default-button" #click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</script>
</head>
<body>
<!-- app -->
<div id="app">
<!-- use the modal component, pass in the prop -->
<modal v-if="showModal" #close="showModal = false">
<!--
you can use custom content here to overwrite
default content
-->
<h3 slot="header">custom header</h3>
</modal>
</div>
</body>
</html>
I was able to construct this using a project with a (relatively) recent example. Here is the component, as well as a 'Tester.vue' view that uses that component:
LoginModal.vue:
<template>
<transition name="modal-fade">
<div class="modal-backdrop">
<div
class="modal"
role="dialog"
aria-labelledby="modalTitle"
aria-describedby="modalDescription"
>
<header class="modal-header" id="modalTitle">
<slot name="header">
</slot>
</header>
<section class="modal-body" id="modalDescription">
<slot name="body">
Your Login Form Goes Here
<button type="button" v-on:click="validateLoginForm">
Log In
</button>
<button type="button" #click="close" aria-label="Close modal">
Cancel
</button>
</slot>
</section>
<footer class="modal-footer">
<slot name="footer"> </slot>
</footer>
</div>
</div>
</transition>
</template>
<script>
export default {
name: "loginModal",
data() {
return {
loginValidationAlerts: [],
};
},
methods: {
close() {
this.$emit("close");
},
validateLoginForm() {
//Login Form Validations go here
},
clearAllLoginValidationErrors() {
this.loginValidationAlerts = [];
},
attemptLogin() {
// Your login code
},
},
};
</script>
<style>
.modal-fade-enter,
.modal-fade-leave-active {
opacity: 0;
}
.modal-fade-enter-active,
.modal-fade-leave-active {
transition: opacity 0.5s ease;
}
.modal-backdrop {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
}
.modal {
background: #ffffff;
box-shadow: 2px 2px 20px 1px;
overflow-x: auto;
display: flex;
flex-direction: column;
}
.modal-header,
.modal-footer {
padding: 15px;
display: flex;
}
.modal-header {
border-bottom: 1px solid #eeeeee;
color: #4aae9b;
justify-content: space-between;
}
.modal-footer {
border-top: 1px solid #eeeeee;
justify-content: flex-end;
}
.modal-body {
position: relative;
padding: 20px 10px;
}
.btn-close {
border: none;
font-size: 20px;
padding: 20px;
cursor: pointer;
font-weight: bold;
color: #4aae9b;
background: transparent;
}
.btn-green {
color: white;
background: #4aae9b;
border: 1px solid #4aae9b;
border-radius: 2px;
}
</style>
Tester.vue:
<template>
<div>
Test Page
<div>
<button type="button" class="btn" #click="showModal">
Open Modal!
</button>
</div>
<div>
<LoginModal v-show="isModalVisible" #close="closeModal"></LoginModal>
</div>
</div>
</template>
<script>
import LoginModal from "#/components/LoginModal.vue";
export default {
components: {
// eslint-disable-next-line vue/no-unused-components
LoginModal,
},
data() {
return {
isModalVisible: false,
};
},
methods: {
showModal() {
// Do something here to determine
// if you should show modal
this.isModalVisible = true;
},
closeModal() {
// this will catch the close event
// after you're done processing the login in the component
this.isModalVisible = false;
},
},
};
</script>
<style scoped></style>
The appearance of the view and its component is pretty rough and without much formatting, but you get the picture.
Hopefully this helps somebody else if they're looking for a straight-forward modal in Vue; I believe it has to be a very common design requirement, and this approach worked for me.
The simple solution is:
add a reference to modal component
<share-modal ref="share-modal-ref"/>
import Modal like this:
import { Modal } from 'bootstrap'
then in your method do this:
let element = this.$refs.listModal.$el
let shareModal = new Modal(element, {})
shareModal.show()
It works on Vue 3 & Boostrap 5
I'm trying to integrate the Accordion component with a body transition, but without success :( . All is working as well except the animation.
template:
<div class="accordion">
<div class="accordion-title" #click="isOpen = !isOpen" :class="{'is-open': isOpen}">
<span>{{title}}</span>
<i class="ic ic-next"></i>
</div>
<div class="accordion-body" :class="{'is-open': isOpen}">
<div class="card">
<slot name="body"></slot>
</div>
</div>
</div>
component:
props: {
title: {
type: String,
default: 'Title'
}
},
data() {
return {
isOpen: false
}
}
And styles:
.accordion-body {
font-size: 1.3rem;
padding: 0 16px;
transition: .3s cubic-bezier(.25,.8,.5,1);
&:not(.is-open) {
display: none;
height: 0;
overflow: hidden;
}
&.is-open {
height: auto;
// display: block;
padding: 16px;
}
}
.card {
height: auto;
}
I tried to use <transition> but it doesn't work with height or display properties.
Help please!
display:none will remove your content and avoid the animation, you should trick with opacity, overflow:hidden and height, but you ll be forced to do a method for that.
For example (not tested, but inspiring):
in template:
<div class="accordion" #click="switchAccordion" :class="{'is-open': isOpen}">
<div class="accordion-title">
<span>{{title}}</span>
<i class="ic ic-next"></i>
</div>
<div class="accordion-body">
<p></p>
</div>
</div>
in component (add a method):
methods: {
switchAccordion: function (event) {
let el = event.target
this.isOpen = !this.isOpen // switch data isOpen
if(this.isOpen) {
let childEl1 = el.childNodes[1]
el.style.height = childEl1.style.height
} else {
let childEl2 = el.childNodes[2]
el.style.height = childE2.style.height // or .clientHeight + "px"
}
}
}
in style:
.accordion {
transition: all .3s cubic-bezier(.25,.8,.5,1);
}
.accordion-body {
font-size: 1.3rem;
padding: 0 16px;
opacity:0
}
.is-open .accordion-body {
opacity:0
}
In this case, your transition should work as you want.
The javascript will change the height value and transition transition: all .3s cubic-bezier(.25,.8,.5,1); will do the animation