Amazing Cards 3D CSS Animation Effect On Mouse Move
In this tutorial we will create a 3d css animation for html boxes. We will attach a javascript event on mouse move and we will animate all elements inside our boxes. To achive this effect we will use css properties like transform, translate, rotate, perspective and many more.
You can see how the effect will look in the below video. There is no need for any css or javascript library, just pure css and js.
Let's create the 3D CSS Animation
This is the CSS code we will use in order to get the required effect. As you can see there are pretty basic css declarations, only few of them are more complex.
*{ margin:0; padding:0; box-sizing:border-box; } html,body{ height:100%; } body{ -webkit-box-align:center; align-items:center; background:#642B73; background:-webkit-gradient(linear, left top, left bottom, from(#C6426E), to(#642B73)); background:linear-gradient(to bottom, #C6426E, #642B73); display:-webkit-box; display:flex; font-family:Open Sans; -webkit-back-pack:center; justify-content:center; overflow:hidden; -webkit-perspective:1800px; perspective:1800px; text-align:center; margin:0 20px; } h1{ color:#3e3e42; font-size:32px;border-image-source: font-weight:800; letter-spacing:-1px; margin-bottom:30px; -webkit-transform:translateZ(35px); transform:translateZ(35px); } h3{ color:#eb285d; font-size:16px; margin-bottom:6px; -webkit-transform:translateZ(25px); transform:translateZ(25px); } .cards{ background:#fff; border-radius:15px; box-shadow:0px 10px 20px 20px rgba(0,0,0,0.17); display:inline-block; padding:30px 35px; -webkit-perspective:1800px; perspective:1800px; text-align:left; -webkit-transform-origin:50% 50%; transform-origin:50% 50%; -webkit-transform-style:preserve-3d; transform-style:preserve-3d; -webkit-transform:rotateX(11deg) rotateY(16.5deg); transform:rotateX(11deg) rotateY(16.5deg); min-width:595px; } .card{ border-radius:15px; box-shadow:5px 5px 20px -5px rgba(0,0,0,0.6); display:inline-block; height:250px; overflow:hidden; -webkit-perspective:1200px; perspective:1200px; position:relative; -webkit-transform-style:preserve-3d; transform-style:preserve-3d; -webkit-transition:-webkit-transform 200ms ease-out; transition:-webkit-transform 200ms ease-out; transition: transform 200ms ease-out; transition: transform 200ms ease-out, -webkit-transform 200ms ease-out; width:175px; text-align: center; } .card:not(:last-child){ margin-right:30px; } .card__img{ position:relative; height:100%; } .card__bg{ bottom:-50px; left:-50px; right:-50px; top:-50px; position:absolute; -webkit-transform-origin:50% 50%; transform-origin:50% 50%; -webkit-transform:translateZ(-50px); transform:translateZ(-50px); z-index:-1; } .card__one .card__img{ top:14px; right:-10px; height:110%; } .card__one .card__bg{ background: url('../images/3dr_monobg.jpg') center/cover no-repeat; } .card__two .card__img{ top:25px; } .card__two .card__bg{ background: url('../images/3dr_spirited.jpg') center/cover no-repeat; } .card__three .card__img{ top:5px; left:-4px; height:110%; } .card__three .card__bg{ background: url('../images/3dr_howlbg.jpg') center/cover no-repeat; } .card__text{ -webkit-box-align:center; align-items:center; background:-webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,0)), to(rgba(0,0,0,0.55))); background:linear-gradient(to bottom, rgba(0,0,0,0) 0%, rgba(0,0,0,0.55) 100%); bottom:0; display:-webkit-box; display:flex; -webkit-box-orient:vertical; -webkit-box-direction:normal; flex-direction: column; height:70px; -webkit-box-pack:center; justify-content:center; position:absolute; width:100%; z-index:2; } .card__title{ color:#fff; font-size:18px; font-weight:700; padding:0 10px; margin-bottom:3px; }
The HTML structure should look like the following:
<!doctype html> <head> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> <link rel="profile" href="https://gmpg.org/xfn/11" /> <link rel="stylesheet" href="css/style.css"> </head> <body> <div class="cards"> <h3>CSS Animations</h3> <h1>Popular</h1> <div class="card card__one"> <div class="card__bg"></div> <img class="card__img" src="images/3dr_mono.png"> <div class="card__text"> <p class="card__title">Princess Mononoke</p> </div> </div> <div class="card card__two"> <div class="card__bg"></div> <img class="card__img" src="images/3dr_chihiro.png"> <div class="card__text"> <p class="card__title">Spirited Away</p> </div> </div> <div class="card card__three"> <div class="card__bg"></div> <img class="card__img" src="images/3dr_howlcastle.png"> <div class="card__text"> <p class="card__title">Howl;s Moving Castle</p> </div> </div> </div> </body> <script type="text/javascript" src="js/main.js"></script> </html>
And finally we have to add the javascript in order to animate the elements as we wish.
const cards = document.querySelector(".cards"); const images = document.querySelectorAll(".card__img"); const backgrounds = document.querySelectorAll(".card__bg"); const range = 40; const calcValue = (a,b) => (a/b * range - range / 2).toFixed(1); let timeout; document.addEventListener('mousemove', ({x,y}) => { if(timeout){ window.cancelAnimationFrame(timeout) } timeouot = window.requestAnimationFrame(() => { const yValue = calcValue(y, window.innerHeight); const xValue = calcValue(x, window.innerWidth); cards.style.transform = `rotateX(${yValue}deg) rotateY(${yValue}deg)`; [].forEach.call(images, image => { image.style.transform = `translateX(${-xValue}px) translateY(${yValue}px)`; }); [].forEach.call(backgrounds, background => { background.style.backgroundPosition = `${xValue * .45}px ${yValue * .45}px`; }); }); }, false);
As you can see in the above code, first of all we set some default css properties for our boxes. Then, in javascript, we create an event listener and attach it to the mouse move. In this way we can change the default properties of the boxes using javascript. In the below video you can see the effect: