Skip to content

Instantly share code, notes, and snippets.

@pmark
Created August 30, 2024 06:55
Show Gist options
  • Save pmark/c4bfd466e5c51ad6f2ad99f9c2e3e24b to your computer and use it in GitHub Desktop.
Save pmark/c4bfd466e5c51ad6f2ad99f9c2e3e24b to your computer and use it in GitHub Desktop.
Parallax Grid with React and Tailwind
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