imagerotationjavascriptcssscrolldev
(updated ) ~4 min (685 words)

Simple on scroll animation with JavaScript and CSS

Partly rotated image of an ara as an on page scroll example

For a side project, I wanted to create an animated picture, which would rotate on page scroll. Here is how it can be done using JavaScript and CSS.


The project

For a side-project idea, I wanted to do include a more unusual effect that would fit the application's purpose.

Since it was about automatically rotating images, rotating an image on scroll seemed to be a perfect fit.

How to rotate an image on scroll

Actually, it's not that much magic involved here. You need some javascript and CSS code and some thinking about when, how far and at which speed the image should rotate when you scroll on the page.

Let's start with the markup:

<div class="container">
    <div class="image-container">
        <img src="rotated-image.png" alt="the image to be rotated on scroll" width="765" height="1080" />
    </div>
</div>

It could be done using a background-image as well, it doesn't really matter. The most important element here is `image-container`.

Right now there would only be an image all over the page. For presentation and clarity, we should increase the canvas height and add some margin at the top so we can see the scrolling.

The CSS should look like this:

.container {
    width: 100vw;
    height: 200vh;
    margin: 3rem 0;
    position: relative;
}

.image-container {
    width: 765px;
    height: auto;
    position: relative;
    display: block;
    margin: 0 auto;
    transform: none;
}

We set the container to a height of `200vh` so we can scroll on that page! Also, we add a margin-top of `3rem` so we can still see the image when scrolling on the page. Therefore, the image container needs a width less than the canvas, which 765px should match in most cases. Additionally, margin-right and margin-left of the image-container are set to auto so we can center the canvas. Lastly, we set the transform to none, here. That's because we any transformation to be disabled at the beginning.

And that's already most of it. Now javascript:

const minTransform = 0;
const maxTransform = 90;
const ScrollThreshold = 5;

let transform = minTransform;

First, we define our base variables:
  1. we want a minimal transformation threshold: minTransform = 0
  2. and a max threshold: maxTransform = 90
  3. the next threshold is at which scroll position we want to start the rotation: scrollThreshold = 5

Last but not least the transformation value should start with the minimal transformation.

And now the rotation function:

function rotate(transform) {
    const image = document.querySelector('.image-container');
    let transformString = 'rotate(' + transform + 'deg)';

    if (image.style.transform !== transformString) {
        image.style.transform = transformString;
    }
}

The main thing we're doing here is getting the image-container and setting the transformation value based on the transformation angle we get as a parameter. As long as it's not the same value, we update the CSS transform value with the rotation transformation.

We still need to track the scroll position and determine the transformation angle by that:

function trackScrollPosition(e) {
    e.preventDefault();

    const step = e.target.scrollingElement.scrollTop;
    const y = window.scrollY;

    if (step <= startThreshold) {
        rotate(0);
        return;
    }

    transform = (step - startThreshold);

    if (transform >= maxTransform) {
        transform = maxTransform;
    } else if (transform <= startThreshold) {
        transform = 0;
    }

    rotate(transform);
}

Long story short we get the current vertical scrolling value and check if that's already above our threshold where we want to start the rotation. If yes, we go on and compute the current angle the image should be rotated to, along the way making sure, we're not getting above or below or max and min thresholds. As soon as we have computed our rotation angle we call the rotate function.

That's almost it, we now need to get the scroll tracking hooked up somewhere:

document.addEventListener("DOMContentLoaded", function(event) {
    document.addEventListener('scroll', trackScrollPosition, false);
});

That's it. Now we have an image that rotates 90 degrees on scrolling the page. Now you can try different variations regarding the rotation or scroll positions.

If you want to see the full code, try https://github.com/bgrande/page-scroll-rotation-example.