React: Scroll Transition for Fancy Portfolios
📅
•🔖web, design

I saw this fancy scrolling effect on this website and it just blew my mind. I thought of recreating it and got somewhat successful :)
BTW, surely check this portfolio website by Ilya Kulbachny.
Setup
Run the following commands to have an initial setup to work on.
git clone https://github.com/holdmypotion/scroll-transition.git
cd scroll-transition
git checkout starter
yarn
yarn start
Final File Structure
heroSection.js
Let's start with the hero section. We'll be using framer-motion
to animate the image on scroll.
Copy paste this code in src/components/heroSection.js
import React from 'react';
// 1.
import { motion, useViewportScroll, useTransform } from 'framer-motion';
import styles from '../styles/heroSection.module.css';
import heroImage from '../assets/images/5.jpeg';
export default function HeroSection({ offset = 1500 }) {
// 2.
const { scrollY } = useViewportScroll();
// 3.
const scale = useTransform(scrollY, [0, offset], [1, 5]);
const opacity = useTransform(scrollY, [0, offset], [3, 0]);
const moveDown = useTransform(scrollY, [0, offset], [0, -1000]);
return (
<>
<div className={styles.imageContainer}>
{/* 4. */}
<motion.img
src={heroImage}
alt='Model'
style={{
opacity: opacity,
scale: scale,
y: moveDown,
}}
/>
</div>
{/* 5. */}
<div style={{ background: '#030303', height: `${offset}px` }}></div>
<div style={{ background: '#030303', height: '80vh' }}></div>
</>
);
}
Let's break it down:
- Here we import all the sass we need from framer motion
- motion: Grants a normal JSX element super powers (extra props to work with framer motion API)
- useViewportScroll: Can be used to track the position of the scroll.
- useTransform: Can be used to change the value of a variable based on a changing value of another variable. (by default: the change is linear)
- We are using the
useViewportScroll
hook to get the vertical scroll distance in pixels - Using the
useTransform
hook to change the value of 3 variables,scale
,opacity
, andmoveDown
based on thescrollY
- Here we pass the dynamic values to the
styles
prop of the motion component. - Lastly, we are adding this empty div of height equal to the total scrolling area we set. This allows us to scroll as the above
imageContainer
is set toposition: fixed