Created
August 30, 2024 06:55
-
-
Save pmark/c4bfd466e5c51ad6f2ad99f9c2e3e24b to your computer and use it in GitHub Desktop.
Parallax Grid with React and Tailwind
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useEffect, useRef } from 'react'; | |
const ParallaxScrolling = () => { | |
const [scrollY, setScrollY] = useState(0); | |
const [contentHeight, setContentHeight] = useState(0); | |
const containerRef = useRef(null); | |
const contentRef = useRef(null); | |
useEffect(() => { | |
const container = containerRef.current; | |
const content = contentRef.current; | |
if (!container || !content) return; | |
const updateContentHeight = () => { | |
setContentHeight(content.scrollHeight); | |
}; | |
const handleScroll = () => { | |
setScrollY(container.scrollTop); | |
}; | |
updateContentHeight(); | |
handleScroll(); | |
const resizeObserver = new ResizeObserver(updateContentHeight); | |
resizeObserver.observe(content); | |
container.addEventListener('scroll', handleScroll, { passive: true }); | |
return () => { | |
resizeObserver.disconnect(); | |
container.removeEventListener('scroll', handleScroll); | |
}; | |
}, []); | |
const cards = [ | |
{ emoji: 'π' }, | |
{ emoji: 'π' }, | |
{ emoji: 'π' }, | |
{ emoji: 'π' }, | |
{ emoji: 'π¦' }, | |
]; | |
const parallaxFactor = 0.5; // Background moves at half the speed of scrolling | |
return ( | |
<div | |
ref={containerRef} | |
className="parallax-container h-screen overflow-y-auto overflow-x-hidden relative" | |
> | |
<div | |
className="parallax-bg fixed inset-0 w-full" | |
style={{ | |
height: `${contentHeight + window.innerHeight}px`, | |
background: `linear-gradient(to bottom, #4a0e8f, #130a2d)`, | |
backgroundSize: '100% 100%', | |
transform: `translateY(${-scrollY * parallaxFactor}px)`, | |
willChange: 'transform', | |
boxShadow: ` | |
inset 0 0 0 2px rgba(255, 255, 255, 0.1), | |
inset 0 0 0 1px rgba(255, 255, 255, 0.05) | |
`, | |
}} | |
> | |
<div | |
className="grid absolute inset-0" | |
style={{ | |
backgroundImage: ` | |
linear-gradient(to right, rgba(255, 255, 255, 0.2) 1px, transparent 1px), | |
linear-gradient(to bottom, rgba(255, 255, 255, 0.2) 1px, transparent 1px) | |
`, | |
backgroundSize: '100px 100px', | |
}} | |
/> | |
</div> | |
<div ref={contentRef} className="parallax-content relative z-10 py-16"> | |
{cards.map((card, index) => ( | |
<div | |
key={index} | |
className="card rounded-lg p-6 my-16 mx-auto w-11/12 h-[95vh] flex items-center justify-center transform transition-all duration-300 hover:scale-105 active:scale-95 overflow-hidden" | |
style={{ | |
backgroundColor: 'rgba(255, 255, 255, 0.1)', | |
backdropFilter: 'blur(8px)', | |
WebkitBackdropFilter: 'blur(8px)', | |
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)', | |
transition: 'all 0.3s ease-in-out, transform 0.1s ease-in-out, box-shadow 0.3s ease-in-out', | |
}} | |
> | |
<div | |
className="card-content w-full h-full flex items-center justify-center relative" | |
style={{ | |
transition: 'all 0.3s ease-in-out', | |
}} | |
> | |
<span className="text-9xl transform transition-transform hover:scale-110 select-none" style={{ color: 'rgba(255, 255, 255, 0.9)' }}> | |
{card.emoji} | |
</span> | |
<div | |
className="card-highlight absolute inset-0 opacity-0 transition-opacity duration-300 pointer-events-none" | |
style={{ | |
boxShadow: 'inset 0 0 20px 5px rgba(255, 255, 255, 0.2)', | |
borderRadius: '0.5rem', | |
}} | |
/> | |
</div> | |
</div> | |
))} | |
</div> | |
</div> | |
); | |
}; | |
export default ParallaxScrolling; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment