Explain Codes LogoExplain Codes Logo

Update style of a component onScroll in React.js

javascript
scroll-events
performance-optimization
react-components
Nikita BarsukovbyNikita BarsukovΒ·Mar 9, 2025
⚑TLDR

Starting with the basics, React styles can be modified dynamically on scroll by leveraging window.scroll event listener. The duo of useState and useEffect from React's arsenal handles state and lifecycle management respectively. Here is a nutshell view:

import React, { useState, useEffect } from 'react'; const DynamicStyleComponent = () => { const [style, setStyle] = useState({}); // Initialize the blank canvas for Van Gogh useEffect(() => { const handleScroll = () => { const scrollTop = window.pageYOffset || document.documentElement.scrollTop; let itemTranslate = Math.min(0, scrollTop / 3); // Math.min, limiting our enthusiasm! setStyle({ transform: `translateY(${itemTranslate}px)` }); }; window.addEventListener('scroll', handleScroll, { passive: true }); return () => window.removeEventListener('scroll', handleScroll); // Cleaning our palette }, []); return <div style={style}>🎨 πŸ–Œ Let's paint the DOM!</div>; };

Above, we have our handleScroll artist that is called on every scroll event, bringing dynamic changes to the styles stored in the state, effectively giving you Van Gogh-like control over transformations in the state of styles. As the saying goes "Less is more", the Math.min precisely serves the same purpose, providing smooth animations by limiting the changes to the styles. Ensuring a clean palette to resume our artistic endeavours, we remove the event listener when the component unmounts, preventing any memory leaks.

The tricks of the trade

Efficiently brushing with throttle

Scroll events might make your function calls an overexcited kid who just got lots of candies, thereby possibly leading to performance nightmares. Thus, throttling these function calls, as shown below will leash and give your users a smoother experience:

import { throttle } from 'lodash'; const handleScroll = throttle(() => { // Hey Picasso, be patient! Let's limit our artistry a bit }, 100); // Let loose the artistry every 100 milliseconds

Responsive styles: catering to all canvases

Tailoring your styles per device is a lot like having different team strategies for home and away games. You adjust the styles based on screen size to provide that "home" like comfort on different devices:

const handleScroll = () => { const width = window.innerWidth || document.documentElement.clientWidth; if (width > 768) { // Away game strategy. You have got ample space! } else { // Home game strategy. Squeeze in! } };

Brushing directly on canvas with refs

For times when you need to make direct changes to the DOM elements instead of the whole component, useRef is your Picasso's brush:

import React, { useRef, useEffect } from 'react'; const DynamicStyleComponentWithRef = () => { const contentRef = useRef(null); // Our canvas is ready! useEffect(() => { const handleScroll = () => { if(contentRef.current) { // Because, Null is just not cool! contentRef.current.style.backgroundPositionY = `${-window.scrollY / 2}px`; } }; window.addEventListener('scroll', handleScroll); return () => window.removeEventListener('scroll', handleScroll); }, []); return <div ref={contentRef}>🎨 Let the magic begin!πŸ–Œ</div>; };

Always ensure to confirm if contentRef.current is a cool guy and not an uncool null before making any moves.

Dynamic toggling of the style wardrobe

To β€œsuit up” your component with multiple set of styles (think CSS rules!) for different occasions (here, scroll positions), try switching the classname based on the scroll position:

const [className, setClassName] = useState('casualWear'); const handleScroll = () => { const scrollTop = window.scrollY || document.documentElement.scrollTop; const newClassName = scrollTop > 500 ? 'formalWear' : 'casualWear'; // Your style wardrobe setClassName(newClassName); }; return <div className={className}>Hello, folks!</div>;

Advanced techniques in the scroll world

Giving a smooth scroll ride with passive event listeners

To make scrolling a smooth drive on the autobahn and not a bumpy ride, we unleash the { passive: true } option. The browser will keep scrolling without having to wait for our JavaScript code to execute preventing scroll lag:

window.addEventListener('scroll', handleScroll, { passive: true }); // The autobahn ride!

Riding the parallax wave

To add extra spice to your user's scroll journey, you can use parallax effects that make background and content move at different pace, creating an immersive 3D-like effect.

const handleScroll = () => { const scrollSpeed = window.scrollY / 2; // Calculate relative speed for an immersive 3D-like effect // Update style with calculated parallax speed };

Lastly, don't forget to clean up your event listeners in the cleanup function to prevent memory leaks.