Add animated menu cards

This commit is contained in:
2025-10-30 14:54:32 +01:00
parent 693484d44c
commit 41cdb5837d
7 changed files with 230 additions and 80 deletions

View File

@@ -11,7 +11,7 @@
<link rel="stylesheet" href="./styles/style.css">
<link rel="stylesheet" href="./styles/introduction.css">
<link rel="stylesheet" href="./styles/projects.css">
<link rel="stylesheet" href="styles/projects.css">
<title>Naaturel</title>
@@ -24,7 +24,7 @@
<h1> Naaturel </h1>
<hr/>
<h2 class="typer"></h2>
</div>
</div>
<footer>
<p>Scroll down to get started</p>
<div><img src="./assets/arrow.svg" alt="arrow"></div>
@@ -32,9 +32,36 @@
</section>
<section id="projects">
<div class="content">
<div>
<h1> Live projects </h1>
<div class="card-list">
<a>
<div class="card">
<h2>My <span class="accentuated">projects</span></h2>
<hr/>
<p>Get a look at what I've worked on</p>
</div>
</a>
<a>
<div class="card">
<h2><span class="accentuated">About</span> me</h2>
<hr/>
<p>Learn more about my skills and background</p>
</div>
</a>
<a>
<div class="card">
<h2><span class="accentuated">Contacts</span></h2>
<hr/>
<p>Get in touch with me</p>
</div>
</a>
</div>
<!--<div class="content">
<div >
<h1>Live projects</h1>
<hr/>
<div class="project-list">
<a href="https://unluckiest.naaturel.be"><img src="./assets/unluckiest.png" alt="unluckiest"></a>
@@ -44,7 +71,7 @@
</div>
<div class="separator"></div>
<div>
<h1> Connect with me! </h1>
<h1>Connect with me!</h1>
<hr/>
<div class="links">
<ul>
@@ -54,7 +81,7 @@
</ul>
</div>
</div>
</div>
</div>-->
</section>
</main>
@@ -71,4 +98,14 @@
typer.start();
</script>
<script type="module">
import {CardTilter} from "./scripts/CardTilter.js";
const cards = document.querySelectorAll('.card');
cards.forEach(card => { new CardTilter({card : card, tilt : 15, perspective : 650}) })
</script>
</html>

10
html/projects.html Normal file
View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>

View File

@@ -0,0 +1,48 @@
export class CardTilter {
/**
*
* @param card Card to be moved
* @param tilt max tilting angle in degree
* @param perspective perspective in pixels
*/
constructor({card : card, tilt : tilt, perspective : perspective}) {
this.card = card;
this.tilt = tilt;
this.perspective = perspective;
this.watch()
}
watch(){
this.card.addEventListener('mousemove', (e) => {
const rotations = this.calculatePositions(e.clientX, e.clientY);
this.transform(rotations.x, rotations.y);
});
this.card.addEventListener('mouseleave', () => {
this.reset();
});
}
calculatePositions(cursorX, cursorY) {
const rect = this.card.getBoundingClientRect();
const x = cursorX - rect.left;
const y = cursorY - rect.top;
const percentX = (x / rect.width) - 0.5;
const percentY = (y / rect.height) - 0.5;
const rotateX = -percentY * this.tilt;
const rotateY = percentX * this.tilt;
return {x : rotateX, y : rotateY};
};
transform(rotationX, rotationY) {
this.card.style.transform = `translateY(-10px) perspective(${this.perspective}px) rotateX(${rotationX}deg) rotateY(${rotationY}deg) scale(1.05)`;
}
reset(){
this.card.style.transform = `rotateX(0deg) rotateY(0deg) scale(1)`;
}
}

View File

@@ -21,6 +21,47 @@ hr {
animation: blink 800ms infinite;
}
.card-list
{
display: flex;
flex-direction: row;
justify-content: start;
gap: 15px;
min-width: 375px;
height: 75%;
overflow: scroll;
padding: 0 20px 0 20px;
}
.card {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
height: 350px;
width: 275px;
background: white;
border-radius: 16px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
padding: 15px;
transition: transform 0.2s ease, box-shadow 0.2s ease;
will-change: transform;
}
.card:hover {
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2);
}
.card p
{
opacity: 0.65;
}
@keyframes blink {
from { opacity: 0; }
to { opacity: 1; }

View File

@@ -1,75 +1,9 @@
#projects .content {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: start;
width: 75%;
}
#projects .content div hr {
margin : 25px 0 25px 0;
}
.project-list, .links {
display: flex;
flex-direction: row;
gap : 1rem;
margin-bottom: 2rem;
}
.project-list img {
width: 215px;
border : solid 1px black;
border-radius: 15px;
transition: transform 0.2s ease-in-out;
}
.project-list img:hover {
transform: scale(1.1);
}
.links {
display: flex;
height: 100%;
font-size: 1.3rem;
}
.links ul {
display: flex;
flex-direction: column;
gap: 40px;
padding : 0;
margin: 0;
}
.links ul li {
#projects {
display: flex;
flex-direction: row;
align-items: center;
padding: 0.5rem 1rem;
border-radius: 10px;
transition: background 0.3s ease;
}
.links ul li:hover {
background: rgba(0, 0, 0, 0.1);
}
.links ul li::before {
content: ">";
margin-right: 1rem;
}
.links ul li:hover::before {
animation: blink 1s step-start infinite;
}
@keyframes blink {
50% {
opacity: 0;
}
justify-content: center;
width: 95%;
height: 95%;
}

View File

@@ -0,0 +1,76 @@
#projects .content {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: start;
width: 75%;
}
#projects .content div hr {
margin : 25px 0 25px 0;
}
.project-list, .links {
display: flex;
flex-direction: row;
gap : 1rem;
margin-bottom: 2rem;
}
.project-list img {
width: 215px;
border : solid 1px black;
border-radius: 15px;
transition: transform 0.2s ease-in-out;
}
.project-list img:hover {
transform: scale(1.1);
}
.links {
display: flex;
height: 100%;
font-size: 1.3rem;
}
.links ul {
display: flex;
flex-direction: column;
gap: 40px;
padding : 0;
margin: 0;
}
.links ul li {
display: flex;
flex-direction: row;
align-items: center;
padding: 0.5rem 1rem;
border-radius: 10px;
transition: background 0.3s ease;
}
.links ul li:hover {
background: rgba(0, 0, 0, 0.1);
}
.links ul li::before {
content: ">";
margin-right: 1rem;
}
.links ul li:hover::before {
animation: blink 1s step-start infinite;
}
@keyframes blink {
50% {
opacity: 0;
}
}

View File

@@ -1,5 +1,5 @@
:root {
--primary-color: #3dae15;
}
::-webkit-scrollbar {
@@ -13,8 +13,8 @@
}
html, body {
height: 100vh;
width: 100vw;
height: 100dvh;
width: 100dvw;
}
html, body, main, section, section div, footer {
@@ -57,4 +57,8 @@ ul li{
ul li a {
text-decoration: none;
}
.accentuated {
color: var(--primary-color);
}