"Hover card"
Bootstrap 4.1.1 Snippet by tranhuuphu

<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <!------ Include the above in your HEAD tag ----------> <a href="#" class="card"> <div class="card__head"> <div class="card__image"></div> <div class="card__author"> <div class="author"> <img src="https://s.gravatar.com/avatar/7ff9e93ff25e002bc49f4d69c0c3eac7?s=80" alt="Author of Tobias Reich" class="author__image"> <div class="author__content"> <p class="author__header">Tobias Reich</p> <p class="author__subheader">Web developer and designer</p> </div> </div> </div> </div> <div class="card__body"> <h2 class="card__headline">Hover me</h2> <p class="card__text">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore.</p> </div> <div class="card__foot"> <span class="card__link">Read more</span> </div> <div class="card__border"></div> </a>
body { display: flex; align-items: center; justify-content: center; width: 100%; min-height: 100vh; font-family: 'Open Sans', sans-serif; color: #333; background: #f8f8f8; } .card { position: relative; display: flex; flex-direction: column; width: 500px; background: white; color: currentColor; text-decoration: none; overflow: hidden; transition-property: color; transition-delay: 0.15s; box-shadow: 0 2px 20px rgba(0, 0, 0, 0.1); } .card.hover { color: white; transition-delay: 0; } .card, .card__image, .card__image::after, .card__author, .card__body, .card__foot, .card__border { transition-duration: 0.4s; transition-timing-function: cubic-bezier(0.51, 0.92, 0.24, 1); } .card__head { position: relative; padding-top: 70%; } .card__author { position: absolute; padding: 2em; left: 0; bottom: 0; color: white; transition-property: -webkit-transform; transition-property: transform; transition-property: transform, -webkit-transform; transition-delay: 0.15s; } .card.hover .card__author { transition-delay: 0; } .card__image { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-size: cover; background-position: center; background-image: url("https://images.unsplash.com/photo-1553787762-b5f5721f3270?ixlib=rb-1.2.1&auto=format&fit=crop&w=2100&q=80"); -webkit-transform-origin: top center; transform-origin: top center; transition-property: -webkit-transform; transition-property: transform; transition-property: transform, -webkit-transform; transition-delay: 0.15s; } .card__image::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; opacity: .5; background: linear-gradient(30deg, rgba(26, 42, 99, 0.85), rgba(26, 42, 99, 0.5)); transition-property: opacity; transition-delay: 0.15s; } .card.hover .card__image { transition-delay: 0; } .card.hover .card__image::after { opacity: 1; transition-delay: 0; } .card__body { position: relative; padding: 2em; transition-property: -webkit-transform; transition-property: transform; transition-property: transform, -webkit-transform; transition-delay: 0.15s; } .card.hover .card__body { transition-delay: 0; } .card__headline { font-weight: 400; margin: 0 0 .8em; } .card__text { line-height: 1.5; margin: 0; opacity: .8; } .card__foot { position: absolute; left: 0; right: 0; bottom: 0; padding: 0 2em 2em; opacity: 0; transition-property: opacity; } .card.hover .card__foot { opacity: 1; transition-delay: 0.15s; } .card__link { color: currentColor; text-decoration: none; border-bottom: 2px solid #b5272d; } .card__border { position: absolute; left: 0; bottom: 0; width: 100%; height: 6px; background: #b5272d; -webkit-transform: scaleY(0); transform: scaleY(0); transition-property: -webkit-transform; transition-property: transform; transition-property: transform, -webkit-transform; } .card.hover .card__border { -webkit-transform: none; transform: none; transition-delay: 0.15s; } .author { display: flex; align-items: center; } .author__image { flex-shrink: 0; margin-right: 1em; width: 56px; height: 56px; border-radius: 100%; overflow: hidden; } .author__content { display: grid; grid-gap: .4em; font-size: .9em; } .author__header { margin: 0; font-weight: 600; } .author__subheader { margin: 0; opacity: .8; }
const height = (elem) => { return elem.getBoundingClientRect().height } const distance = (elemA, elemB, prop) => { const sizeA = elemA.getBoundingClientRect()[prop] const sizeB = elemB.getBoundingClientRect()[prop] return sizeB - sizeA } const factor = (elemA, elemB, prop) => { const sizeA = elemA.getBoundingClientRect()[prop] const sizeB = elemB.getBoundingClientRect()[prop] return sizeB / sizeA } document.querySelectorAll('.card').forEach((elem) => { const head = elem.querySelector('.card__head') const image = elem.querySelector('.card__image') const author = elem.querySelector('.card__author') const body = elem.querySelector('.card__body') const foot = elem.querySelector('.card__foot') elem.onmouseenter = () => { elem.classList.add('hover') const imageScale = 1 + factor(head, body, 'height') image.style.transform = `scale(${ imageScale })` const bodyDistance = height(foot) * -1 body.style.transform = `translateY(${ bodyDistance }px)` const authorDistance = distance(head, author, 'height') author.style.transform = `translateY(${ authorDistance }px)` } elem.onmouseleave = () => { elem.classList.remove('hover') image.style.transform = `none` body.style.transform = `none` author.style.transform = `none` } })

Related: See More


Questions / Comments: