3D Hover Animation Effect
Introduction:
Welcome to our channel! In this mesmerizing coding tutorial, we're diving into the captivating world of 3D hover animation effects using HTML, CSS, and JavaScript. 🔥✨
🌐 Learn the secrets behind creating a mind-blowing 3D hover animation that will leave your website visitors in awe. Whether you're a coding enthusiast or a web development pro, this step-by-step guide will take you through every line of code, ensuring you grasp the concepts effortlessly.
🚀 Why you should watch this tutorial:
In-depth explanation: We leave no stone unturned, providing clear and concise explanations for each code snippet.
Practical examples: Real-world examples illustrate the concepts, making it easier for you to apply them to your own projects.
Beginner to advanced: Whether you're new to coding or looking to enhance your skills, this tutorial caters to all levels.
VIDEO
Optimization for YouTube's ranking algorithm: We've designed this video to adhere to YouTube's policies, enhancing its visibility and increasing its chances of going viral.
Engaging and immersive: Our goal is not only to teach but to captivate. You'll witness the stunning results of your coding efforts firsthand.
📋 What we'll cover in this tutorial:
Setting up the HTML structure for the animation container.
Crafting CSS styles to create a captivating 3D effect on hover.
Adding smooth transitions for a polished user experience.
Implementing JavaScript interactivity to elevate the animation to the next level.
Html Code:
<!DOCTYPE html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<meta name ="viewport" content ="width=device-width, initial-scale=1.0" >
<title >3D Hover Effet</title >
<link rel ="stylesheet" href ="style.css" >
</head >
<body >
<div class ="centered" >
<div class ="card border-left-behind" >
<div class ="shadow" style =" --url: url('https://i.ibb.co/PM4ghD4/full.png')" ></div >
<div class ="image background" style =" --url: url('https://i.ibb.co/JpJVJxq/Background.png')" ></div >
<div class ="image cutout" style =" --url: url('https://i.ibb.co/Dw3q3tZ/cutout.png')" ></div >
<div class ="content" >
<h2 >Hover me!</h2 >
<p >Lorem, ipsum dolor sit amet consectetur adipisicing elit.</p >
</div >
</div >
<div class ="card border-right-behind border-bottom-behind" >
<div class ="shadow" style =" --url: url('https://i.ibb.co/DC0MbxS/m-full.png')" ></div >
<div class ="image background"
style =" --url: url('https://i.ibb.co/ZdGBm4K/m-background.png')" ></div >
<div class ="image cutout" style =" --url: url('https://i.ibb.co/RC70XmC/m-cutout.png')" ></div >
<div class ="content" >
<h2 >Hover me!</h2 >
<p >Lorem, ipsum dolor sit amet consectetur adipisicing elit.</p >
</div >
</div >
<div class ="card border-left-behind" >
<div class ="shadow" style =" --url: url('https://i.ibb.co/gSBp82C/b-full.png')" ></div >
<div class ="image background"
style =" --url: url('https://i.ibb.co/MDBcyMW/b-background.png')" ></div >
<div class ="image cutout" style =" --url: url('https://i.ibb.co/bQNgD6y/b-cutout.png')" ></div >
<div class ="content" >
<h2 >Hover me!</h2 >
<p >Lorem, ipsum dolor sit amet consectetur adipisicing elit.</p >
</div >
</div >
</div >
</body >
<script src ="script.js" ></script >
</html >
Css Code:@import url ("https://fonts.googleapis.com/css2?family=Montserrat:wght@300;700&display=swap" );
html ,
body {
width: 100% ;
height: 100% ;
font-family: "Montserrat" , sans-serif ;
}
.centered {
display: flex;
align-items: center;
justify-content: center;
gap: 3rem ;
height: 100% ;
}
.card {
position: relative;
height: 28rem ;
width: 20rem ;
aspect-ratio: 5 /7 ;
color: # ffffff ;
perspective: 50rem ;
}
.card .shadow {
position: absolute;
inset: 0 ;
background: var (--url );
background-size: cover;
background-position: center;
opacity: 0.8 ;
filter: blur (2rem ) saturate (0.9 );
box-shadow: 0 -1.5rem 2rem -0.5rem rgba (0 , 0 , 0 , 0.7 );
transform: rotateX (var (--rotateX )) rotateY (var (--rotateY )) translate3d (0 , 2rem , -2rem );
}
.card .image {
position: absolute;
inset: 0 ;
background: linear-gradient (to top, rgba (0 , 0 , 0 , 0.5 ), transparent 40% ), var (--url );
background-size: cover;
background-position: center;
-webkit-mask-image : var (--url );
mask-image: var (--url );
-webkit-mask-size : cover;
mask-size: cover;
-webkit-mask-position : center;
mask-position: center;
}
.card .image.background {
transform: rotateX (var (--rotateX )) rotateY (var (--rotateY )) translate3d (0 , 0 , 0rem );
}
.card .image.cutout {
transform: rotateX (var (--rotateX )) rotateY (var (--rotateY )) translate3d (0 , 0 , 4rem ) scale (0.92 );
z-index: 3 ;
}
.card .content {
position: absolute;
display: flex;
flex-direction: column;
justify-content: flex-end;
inset: 0 ;
padding: 3.5rem ;
transform: rotateX (var (--rotateX )) rotateY (var (--rotateY )) translate3d (0 , 0 , 6rem );
z-index: 4 ;
}
.card::after ,
.card::before {
content: "" ;
position: absolute;
inset: 1.5rem ;
border: # e2c044 0.5rem solid;
transform: rotateX (var (--rotateX )) rotateY (var (--rotateY )) translate3d (0 , 0 , 2rem );
}
.card::before {
z-index: 4 ;
}
.card.border-left-behind::before {
border-left: transparent;
}
.card.border-right-behind::before {
border-right: transparent;
}
.card.border-bottom-behind::before {
border-bottom: transparent;
}
h2 {
font-size: 1.25rem ;
font-weight: 700 ;
margin-bottom: 0.5rem ;
text-shadow: 0 0 2rem rgba (0 , 0 , 0 , 0.5 );
}
p {
font-weight: 300 ;
text-shadow: 0 0 2rem rgba (0 , 0 , 0 , 0.5 );
}
Javascript Code:
const angle = 20 ;
const rotateCard = window;
const lerp = (start, end, amount) => {
return (1 - amount) * start + amount * end;
};
const remap = (value, oldMax, newMax) => {
const newValue = ((value + oldMax) * (newMax * 2 )) / (oldMax * 2 ) - newMax;
return Math.min (Math.max (newValue, - newMax), newMax);
};
window.addEventListener ("DOMContentLoaded" , (event) => {
const cards = document.querySelectorAll (".card" );
cards.forEach ((e) => {
e.addEventListener ("mousemove" , (event) => {
const rect = e.getBoundingClientRect ();
const centerX = (rect.left + rect.right ) / 2 ;
const centerY = (rect.top + rect.bottom ) / 2 ;
const posX = event.pageX - centerX;
const posY = event.pageY - centerY;
const x = remap (posX, rect.width / 2 , angle);
const y = remap (posY, rect.height / 2 , angle);
e.dataset .rotateX = x;
e.dataset .rotateY = - y;
});
e.addEventListener ("mouseout" , (event) => {
e.dataset .rotateX = 0 ;
e.dataset .rotateY = 0 ;
});
});
const update = () => {
cards.forEach ((e) => {
let currentX = parseFloat (e.style .getPropertyValue ('--rotateY' ).slice (0 , - 1 ));
let currentY = parseFloat (e.style .getPropertyValue ('--rotateX' ).slice (0 , - 1 ));
if (isNaN (currentX)) currentX = 0 ;
if (isNaN (currentY)) currentY = 0 ;
const x = lerp (currentX, e.dataset .rotateX , 0.05 );
const y = lerp (currentY, e.dataset .rotateY , 0.05 );
e.style .setProperty ("--rotateY" , x + "deg" );
e.style .setProperty ("--rotateX" , y + "deg" );
})
}
setInterval (update, 1000 / 60 )
});