How to create Parallax Scrolling transitions using CSS in a Web Page

Updated: 3 days ago

Have you seen amazing CSS effects in video games or marketing pages, and want to know how they work? In this post, we show you the anatomy of these effects and how to replicate them 🕵

Reverse engineering application at to learn about its Effect Transitions

Don't worry! Even if you haven't played League of Legends or if you don't know much about CSS here's a short explanation of both

League of Legends is a team-based strategy game in which two teams of five champions battle it out to see who can destroy the other team's base first. Choose from a cast of 140 champions to perform epic moves, assassinate opponents, and takedown turrets to claim victory.

Looking beyond the Arcane Serie, (Arcane is an animated series set in the League of Legends universe, which by the way, is very very good <3 you have to watch it!) that you've surely heard of, this time we'll talk about web marketing page and its CSS effects, i.e. scroll, parallax, images, and transitions that caught our attention, we researched and would like to share with you.

The visual effects of both (the series and the website) look very good, the animation is considered first-class and the developers made sure to bring the audience some visual pleasure.

Arcane CSS Effects


Arcane Web Page

The newly launched content in November includes an eye-catching user experience web page hosted on the marketing site for Netflix:, there you will find a very nice brushstroke effect that changes the background while exploring the site, which we will call the Parallax Brush Scrolling Effect.

This whole effect has been split into 4 parts.

1. Scroll Effect

If there is an error with the player, you can watch the video at the following LINK.

First, we need a container with a height greater than the height of the screen, the image that will have the size of the screen with the sticky position so that it always stands and stays on the top.

import styled from "styled-components";

const StyledContainer = styled.div`
  height: 300vh;

// Styled component named StyledContainer
const StyledSection = styled.div`
  height: 100vh;
  position: sticky;
  top: 0;
  • position: sticky; Used when needed that an element stays in the same place on scroll for a portion of the page. It’s straightforward and built into modern browsers.

2. Parallax Effect

It is basically the sensation of an apparent displacement of the images or objects when observed from different points as if they had dimension and at the same time movement resulting from the movement of the scroll.

Parallax scrolling is a website trend where the background content (image) is moved at a different speed than the foreground content while scrolling, and to create it we will need the following CSS properties:

  • Transform: This allows you to modify the coordinate space of the CSS visual formatting model. Using it, elements can be translated, rotated, scaled, or skewed according to the set values.

  • Translate(): It relocates an element on the horizontal and/or vertical axis. Its result is composed of a two-dimensional vector whose coordinates define how much the element will move in each direction.

What is the effect about?

If there is an error with the player, you can watch the video at the following LINK.

3. Mask Image

CSS masking gives you the option to use an image as a mask layer. This means that you can use an image, an SVG, or a gradient as a mask, to create interesting effects without the need for an image editor.

Mask Image applies a mask to the image, imagine one image on top of another, and this mask multiplies the transparency channel of the image behind it against its own color alpha value, i.e. if the image behind it in its value is zero, the mask will also be completely transparent.

So when scrolling the images are resized as the mask. For this, we will use two images:

  • Zaún: Our front image.

To download the HD image, visit LINK.

  • Piltover: This will be our background image, which will also have two masks: - A gradient: That changes the mask size according to scroll - The brush (4. Brushstrokes ) to which only the mask position will be modified

To download the HD image, visit LINK.

The mask-image property specifies an image to be used as a mask layer for an element (Linear and radial gradients in CSS can also be used as the mask image).

import { maskImage } from './resources';

const StyledBackgroundMask = styled.div.attrs(
  ({ brushPosition, gradientSize, maskImage }) => ({
    style: {

      `linear-gradient(black 0%, black 100%), url(${maskImage})`,
      `100% ${gradientSize >= 0 ? gradientSize : 0}px, 100%`,

      `0px 0px, 0px ${brushPosition}px`,
  position: absolute;
  height: 100vh;
  width: 100vw;
  background-color: red;
  mask-repeat: no-repeat;

For the background, in WebkitMaskImage we will contain two masks separated by commas: first, a linear gradient from 0% to 100%, and the second one is the URL to the brush image.

WebkitMaskSize In this variable we have the size of the gradient, and as we only want the brush to move its size will be kept at 100%.

WebkitMaskPosition And in the position the first two are the position of the gradient and the others are the positions of the brush, that is to say, the vertical is modified as you scroll.

In the following video we show you the implementations and how they would look together:

If there is an error with the player, you can watch the video at the following LINK.

4. Brushstrokes

The effect of the brushstrokes when scrolling is made thanks to some assets or animation frames that were previously exported to PNG format, here is the download link: BrushSprites.

From these 31 frames, an array of positions is created and adjusted depending on the positions when scrolling in x and y, also width and height values are added. Also, we can define how many scroll units to change from frame 1 to the next one and so on, with the help of the following function:

const BrushMask = ({ size, options }) => {
  const [frame, setFrame] = useState(0);

  useEffect(() => {
    const onScroll = () => {
      setFrame(Math.floor(window.scrollY / 10) % 31);

    window.addEventListener('scroll', onScroll);
  }, []);

So, the (position of the scroll/10) modulo 31, means basically that every 10 scroll units, the function will change the frame until it reaches 31 frames and then the brush goes down and restart the animation, but from the new position (lower).

Finally, the background will progress with the brushstroke.

Let's see how it works!

If there is an error with the player, you can watch the video at the following LINK.

Remember, that this is a reverse engineering experiment, find the link to the repo project here.


¡Thanks for reading!


Join our newsletter to receive information about latest technologies trends and job offers

Thanks for subscribing!