<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`
}
})