feat(interaction): implement sophisticated hover effects and parallax

- Add moving shine effect and glow on card hover
- Implement coffee drip animation for link underlines
- Add JS-driven parallax scroll effect for floating elements
- Enhance button micro-interactions
- Refine animations for smoothness
This commit is contained in:
2026-02-12 09:19:20 -05:00
parent 87505afd68
commit 8883b5487b
2 changed files with 85 additions and 13 deletions

27
main.js
View File

@@ -154,6 +154,32 @@ function initTestimonials() {
});
}
// ===== PARALLAX EFFECT FOR DECORATIVE ELEMENTS =====
function initParallax() {
const floatingElements = document.querySelectorAll('.floating-bean, .floating-cup');
if (!floatingElements.length) return;
let ticking = false;
window.addEventListener('scroll', () => {
if (!ticking) {
window.requestAnimationFrame(() => {
const scrolled = window.scrollY;
floatingElements.forEach((el, index) => {
const speed = 0.05 + (index * 0.02); // Vary speed per element
const yPos = -(scrolled * speed);
// Use CSS variable to avoid overwriting the float animation transform
el.style.transform = `translateY(${yPos}px)`;
});
ticking = false;
});
ticking = true;
}
}, { passive: true });
}
// ===== INITIALIZE ALL =====
document.addEventListener('DOMContentLoaded', () => {
initTypewriter();
@@ -161,4 +187,5 @@ document.addEventListener('DOMContentLoaded', () => {
initSkillBars();
initParticles();
initTestimonials();
initParallax();
});

View File

@@ -139,7 +139,8 @@ body {
position: absolute;
opacity: 0.04;
color: var(--color-coffee-dark);
animation: float-cup 18s infinite ease-in-out;
animation: float-rotate 18s infinite ease-in-out;
transition: transform 0.1s linear;
}
@media (prefers-color-scheme: dark) {
@@ -151,10 +152,17 @@ body {
.cup-1 { width: 120px; top: 25%; right: 10%; animation-delay: -2s; }
@keyframes float-cup {
0% { transform: translate(0, 0) rotate(-5deg); }
50% { transform: translate(-20px, 30px) rotate(5deg); }
100% { transform: translate(0, 0) rotate(-5deg); }
@keyframes float-rotate {
0% { transform: rotate(-5deg); }
50% { transform: rotate(5deg); }
100% { transform: rotate(-5deg); }
}
@keyframes float-rotate {
0% { transform: rotate(-5deg); }
50% { transform: rotate(5deg); }
100% { transform: rotate(-5deg); }
}
/* Coffee Stains */
@@ -257,12 +265,25 @@ a {
color: var(--color-primary);
text-decoration: none;
font-weight: 600;
transition: text-decoration-color 0.2s;
position: relative;
transition: color 0.3s ease;
/* Coffee Drip Underline Animation */
background-image: linear-gradient(to right, var(--color-coffee-medium) 0%, var(--color-gold) 100%);
background-size: 0% 2px;
background-position: left bottom;
background-repeat: no-repeat;
padding-bottom: 2px;
&:hover {
text-decoration: underline;
text-decoration-thickness: 2px;
text-underline-offset: 4px;
background-size: 100% 2px;
color: var(--color-coffee-dark);
}
}
@media (prefers-color-scheme: dark) {
a:hover {
color: var(--color-gold);
}
}
@@ -398,10 +419,11 @@ section {
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid var(--border-subtle);
border-radius: 16px; /* Increased radius */
border-radius: 16px;
overflow: hidden;
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
height: 100%;
position: relative;
/* Scroll Animation Entry */
view-timeline-name: --card-entry;
@@ -413,15 +435,38 @@ section {
&:hover {
transform: translateY(-8px) scale(1.02);
box-shadow: var(--shadow-glass);
border-color: var(--color-gold); /* Gold Accent */
border-color: var(--color-gold);
background-color: color-mix(in srgb, var(--bg-surface), var(--color-cream) 10%);
}
/* Shine Effect */
&::after {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.2),
transparent
);
transition: 0.5s;
pointer-events: none;
}
&:hover::after {
left: 100%;
transition: 0.7s ease-in-out;
}
.card-img-top {
aspect-ratio: 16/9;
object-fit: cover;
transition: transform 0.6s ease;
filter: sepia(20%) contrast(1.1); /* Subtle coffee tint */
filter: sepia(20%) contrast(1.1);
}
&:hover .card-img-top {
@@ -435,7 +480,7 @@ section {
flex-direction: column;
h5.card-title {
font-size: 1.5rem; /* Larger */
font-size: 1.5rem;
margin-bottom: 0.75rem;
font-family: var(--font-display);
letter-spacing: -0.02em;