3D Card Hover Effect Gallery with HTML, CSS & JavaScript
40 DAYS 40 PROJECT CHALLENGE
Day #31
Project Overview
The 3D Card Hover Effect Gallery is an interactive frontend project built using HTML, CSS, and JavaScript. It displays a collection of image cards that respond to the user’s cursor with a smooth 3D tilt effect. As the cursor moves across a card, the card changes its rotation based on the cursor position, creating a sense of depth and movement.
First, HTML creates the gallery and adds image cards with titles and descriptions. Next, CSS uses transform-style: preserve-3d and transition effects to prepare the cards for the 3D interaction. Finally, JavaScript tracks the mouse position and calculates the required rotateX() and rotateY() values. When the cursor leaves a card, JavaScript resets the transformation to return the card to its original position. This project is useful for learning CSS transforms, perspective-style effects, mouse events, and interactive UI design.
Key Features
- Interactive 3D Hover Effect: Each card tilts according to the user’s cursor movement. This creates a dynamic depth effect that makes the gallery more engaging.
- Multiple Gallery Cards: The project includes cards for Mountain, City, Ocean, and Forest images. Each card contains an image, title, and short description.
- Dynamic Tilt Rotation: JavaScript calculates the cursor’s position inside each card and converts it into
rotateX()androtateY()values. Therefore, the card follows the cursor movement. - Smooth Animation: CSS uses a short transition on the card transformation. As a result, the movement appears smooth rather than changing position suddenly.
- 3D Transform Support: The cards use
transform-style: preserve-3dto maintain their 3D transformation. This property helps create the visual depth used by the hover effect. - Scale Effect on Hover: The JavaScript slightly increases the card size while the cursor is over it. This combines scaling with rotation to make the interaction more noticeable.
- Responsive Gallery Layout: CSS Grid uses
auto-fitandminmax()to arrange the cards based on the available screen width. This allows the gallery to adapt to different devices. - Clean Card Design: Each card uses rounded corners, a white background, an image section, and a content area. A soft shadow also helps separate the cards from the page background.
- Mouse Interaction: JavaScript uses the
mousemoveevent to continuously update the card transformation. Themouseleaveevent then resets the card when the cursor moves away. - Reusable UI Component: The card structure can be reused for portfolios, product showcases, image galleries, and other modern website sections.
What You'll Learn
- How to create a card-based gallery using HTML
- How to build responsive layouts with CSS Grid
- How CSS
transform-stylecreates 3D effects - How to use
rotateX()androtateY()transformations - How to handle
mousemoveandmouseleaveevents - How to calculate cursor position inside an element
- How to combine rotation and scaling effects
- How JavaScript can create interactive UI animations
HTML Code
The HTML creates the structure of the 3D card gallery. First, it adds a main heading and a .gallery container that holds all the cards. Each .card contains an image and a .card-info section. The information section includes a heading and description, such as Mountain – Beautiful landscape view or City – Urban skyline at night.
Finally, the JavaScript file is loaded at the bottom of the page. This allows JavaScript to select the cards and add the mouse interaction needed for the 3D effect.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>3D Card Hover Gallery</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>3D Card Hover Effect Gallery</h1>
<div class="gallery">
<div class="card">
<img src="https://picsum.photos/300/200?1">
<div class="card-info">
<h3>Mountain</h3>
<p>Beautiful landscape view</p>
</div>
</div>
<div class="card">
<img src="https://picsum.photos/300/200?2">
<div class="card-info">
<h3>City</h3>
<p>Urban skyline at night</p>
</div>
</div>
<div class="card">
<img src="https://picsum.photos/300/200?3">
<div class="card-info">
<h3>Ocean</h3>
<p>Peaceful ocean waves</p>
</div>
</div>
<div class="card">
<img src="https://picsum.photos/300/200?5">
<div class="card-info">
<h3>Forest</h3>
<p>Nature green forest</p>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html> CSS Code
The CSS creates the gallery layout and prepares each card for the 3D interaction. First, the .gallery uses CSS Grid with repeat(auto-fit, minmax(250px, 1fr)), allowing the cards to automatically adjust according to the available space. Next, each .card uses a white background, rounded corners, hidden overflow, and a box shadow. The transform-style: preserve-3d property allows the card to maintain its 3D transformation.
The card images use object-fit: cover so they fill the image area without distorting their proportions. Meanwhile, the transition on the card makes the JavaScript-controlled transformations appear smooth.
*{
margin:0;
padding:0;
box-sizing:border-box;
font-family:Arial;
}
body{
background:#042354;
padding:40px;
text-align:center;
color:white;
}
h1{
margin-bottom:40px;
}
.gallery{
display:grid;
grid-template-columns:repeat(auto-fit,minmax(250px,1fr));
gap:30px;
max-width:1000px;
margin:auto;
}
.card{
background:white;
border-radius:12px;
overflow:hidden;
transform-style:preserve-3d;
transition:transform 0.2s;
box-shadow:0 10px 25px rgba(0,0,0,0.2);
cursor:pointer;
}
.card img{
width:100%;
height:180px;
object-fit:cover;
}
.card-info{
padding:15px;
color:#111;
}
.card-info h3{
margin-bottom:5px;
} Javascript Code
JavaScript controls the interactive 3D movement. First, querySelectorAll() selects all elements with the .card class, and forEach() adds event listeners to every card. Next, the mousemove event gets the card’s position using getBoundingClientRect(). JavaScript calculates the cursor’s distance from the center of the card and converts those values into rotateX() and rotateY() angles.
After that, the code applies the rotation along with a scale(1.05) effect using the card’s style.transform property. Finally, the mouseleave event resets the transformation to rotateX(0) rotateY(0), returning the card to its original position.
const cards = document.querySelectorAll(".card")
cards.forEach(card => {
card.addEventListener("mousemove", e => {
const rect = card.getBoundingClientRect()
const x = e.clientX - rect.left
const y = e.clientY - rect.top
const centerX = rect.width / 2
const centerY = rect.height / 2
const rotateX = -(y - centerY) / 10
const rotateY = (x - centerX) / 10
card.style.transform =
`rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(1.05)`
})
card.addEventListener("mouseleave", () => {
card.style.transform = "rotateX(0) rotateY(0)"
})
}) Related Projects
Day 28 : Theme Customizer Panel
Allows users to customize UI themes with real-time preview.
Concepts: CSS variables, state management, dynamic styling.
Day 29 : Web Accessibility Analyzer
Analyzes website accessibility and highlights improvement areas.
Concepts: DOM analysis, accessibility checks, UI feedback.
Day 33 : Drag & Drop Website Section Builder
Builds webpage sections using drag-and-drop components.
Concepts: Drag & drop API, dynamic layout, DOM manipulation.