Vue Fancy Animated Cards
Vue card help to display small content with image and hover effect. It gives a fancy look to your catlog and product page. You can display your category with some images and small text with hover effect. On hover you’ll see a fancy animation on cards.
HTML
<h1 class="title">Hover over the cards</h1> <div id="app" class="container"> <card data-image="https://images.unsplash.com/photo-1479660656269-197ebb83b540?dpr=2&auto=compress,format&fit=crop&w=1199&h=798&q=80&cs=tinysrgb&crop="> <h1 slot="header">Canyons</h1> <p slot="content">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> </card> <card data-image="https://images.unsplash.com/photo-1479659929431-4342107adfc1?dpr=2&auto=compress,format&fit=crop&w=1199&h=799&q=80&cs=tinysrgb&crop="> <h1 slot="header">Beaches</h1> <p slot="content">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> </card> <card data-image="https://images.unsplash.com/photo-1479644025832-60dabb8be2a1?dpr=2&auto=compress,format&fit=crop&w=1199&h=799&q=80&cs=tinysrgb&crop="> <h1 slot="header">Trees</h1> <p slot="content">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> </card> <card data-image="https://images.unsplash.com/photo-1479621051492-5a6f9bd9e51a?dpr=2&auto=compress,format&fit=crop&w=1199&h=811&q=80&cs=tinysrgb&crop="> <h1 slot="header">Lakes</h1> <p slot="content">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p> </card> </div> |
CSS
$hoverEasing: cubic-bezier(0.23, 1, 0.32, 1); $returnEasing: cubic-bezier(0.445, 0.05, 0.55, 0.95); body { margin: 40px 0; font-family: "Raleway"; font-size: 14px; font-weight: 500; background-color: #BCAAA4; -webkit-font-smoothing: antialiased; } .title { font-family: "Raleway"; font-size: 24px; font-weight: 700; color: #5D4037; text-align: center; } p { line-height: 1.5em; } h1+p, p+p { margin-top: 10px; } .container { padding: 40px 80px; display: flex; flex-wrap: wrap; justify-content: center; } .card-wrap { margin: 10px; transform: perspective(800px); transform-style: preserve-3d; cursor: pointer; // background-color: #fff; &:hover { .card-info { transform: translateY(0); } .card-info p { opacity: 1; } .card-info, .card-info p { transition: 0.6s $hoverEasing; } .card-info:after { transition: 5s $hoverEasing; opacity: 1; transform: translateY(0); } .card-bg { transition: 0.6s $hoverEasing, opacity 5s $hoverEasing; opacity: 0.8; } .card { transition: 0.6s $hoverEasing, box-shadow 2s $hoverEasing; box-shadow: rgba(white, 0.2) 0 0 40px 5px, rgba(white, 1) 0 0 0 1px, rgba(black, 0.66) 0 30px 60px 0, inset #333 0 0 0 5px, inset white 0 0 0 6px; } } } .card { position: relative; flex: 0 0 240px; width: 240px; height: 320px; background-color: #333; overflow: hidden; border-radius: 10px; box-shadow: rgba(black, 0.66) 0 30px 60px 0, inset #333 0 0 0 5px, inset rgba(white, 0.5) 0 0 0 6px; transition: 1s $returnEasing; } .card-bg { opacity: 0.5; position: absolute; top: -20px; left: -20px; width: 100%; height: 100%; padding: 20px; background-repeat: no-repeat; background-position: center; background-size: cover; transition: 1s $returnEasing, opacity 5s 1s $returnEasing; pointer-events: none; } .card-info { padding: 20px; position: absolute; bottom: 0; color: #fff; transform: translateY(40%); transition: 0.6s 1.6s cubic-bezier(0.215, 0.61, 0.355, 1); p { opacity: 0; text-shadow: rgba(black, 1) 0 2px 3px; transition: 0.6s 1.6s cubic-bezier(0.215, 0.61, 0.355, 1); } * { position: relative; z-index: 1; } &:after { content: ''; position: absolute; top: 0; left: 0; z-index: 0; width: 100%; height: 100%; background-image: linear-gradient(to bottom, transparent 0%, rgba(#000, 0.6) 100%); background-blend-mode: overlay; opacity: 0; transform: translateY(100%); transition: 5s 1s $returnEasing; } } .card-info h1 { font-family: "Playfair Display"; font-size: 36px; font-weight: 700; text-shadow: rgba(black, 0.5) 0 10px 10px; } |
VueJS
Vue.config.devtools = true; Vue.component('card', { template: ` <div class="card-wrap" @mousemove="handleMouseMove" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" ref="card"> <div class="card" :style="cardStyle"> <div class="card-bg" :style="[cardBgTransform, cardBgImage]"></div> <div class="card-info"> <slot name="header"></slot> <slot name="content"></slot> </div> </div> </div>`, mounted() { this.width = this.$refs.card.offsetWidth; this.height = this.$refs.card.offsetHeight; }, props: ['dataImage'], data: () => ({ width: 0, height: 0, mouseX: 0, mouseY: 0, mouseLeaveDelay: null }), computed: { mousePX() { return this.mouseX / this.width; }, mousePY() { return this.mouseY / this.height; }, cardStyle() { const rX = this.mousePX * 30; const rY = this.mousePY * -30; return { transform: `rotateY(${rX}deg) rotateX(${rY}deg)` }; }, cardBgTransform() { const tX = this.mousePX * -40; const tY = this.mousePY * -40; return { transform: `translateX(${tX}px) translateY(${tY}px)` } }, cardBgImage() { return { backgroundImage: `url(${this.dataImage})` } } }, methods: { handleMouseMove(e) { this.mouseX = e.pageX - this.$refs.card.offsetLeft - this.width/2; this.mouseY = e.pageY - this.$refs.card.offsetTop - this.height/2; }, handleMouseEnter() { clearTimeout(this.mouseLeaveDelay); }, handleMouseLeave() { this.mouseLeaveDelay = setTimeout(()=>{ this.mouseX = 0; this.mouseY = 0; }, 1000); } } }); const app = new Vue({ el: '#app' }); |
See live demo and download source code.
DEMO | DOWNLOAD
This awesome script developed by andymerskin. Visit their official repository for more information and follow for future updates.