JSFiddle - React, Tailwind, and code Playground
HTML
<div class="box-container">
<div class="box">
<div class="front">1</div>
<div class="back">1</div>
</div>
<div class="box">
<div class="front">2</div>
<div class="back">2</div>
</div>
<div class="box">
<div class="front">3</div>
<div class="back">3</div>
</div>
<div class="box">
<div class="front">4</div>
<div class="back">4</div>
</div>
</div>
SCSS
* {
box-sizing: border-box;
}
.box-container {
padding: 20px;
&:after {
content: '';
display: block;
clear: both;
}
.box {
float: left;
width: 50%;
height: 200px;
position: relative;
perspective: 1000px;
border: 1px solid transparent;
.front,
.back {
float: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transform-style: preserve-3d;
backface-visibility: hidden;
}
.front {
background: blue;
transform: rotateX(0) rotateY(0);
z-index: 900;
}
.back {
background: red;
z-index: 800;
}
}
}
JavaScript
$('.box-container .box').each(function() {
$(this).on('mouseenter mouseleave', function(e) {
var $this = $(this),
width = $this.width(),
height = $this.height();
var x = (e.pageX - $this.offset().left - (width / 2)) * (width > height ? (height / width) : 1),
y = (e.pageY - $this.offset().top - (height / 2)) * (height > width ? (width / height) : 1);
// top = 0, right = 1, bottom = 2, left = 3
var dir_num = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4;
var degrees = 179 * (dir_num > 1 ? 1 : -1) * (e.type === 'mouseenter' ? 1 : -1);
var el_class = e.type === 'mouseenter' ? '.front' : '.back';
var axis = dir_num % 2 ? 'Y' : 'X';
$this.children(el_class)
.animate({transform: degrees}, {
step: function(now, fx) {
$(this).css('transform', 'rotate'+ axis + '(' + now + 'deg)');
},
duration: 400
})
.siblings()
.animate({transform: degrees}, {
step: function(now, fx) {
$(this).css('transform', 'rotate'+ axis + '(' + (degrees - now) + 'deg)');
},
duration: 400
});
});
});