Best way to create this animation on scroll

Hi there,

I am wanting to create an animation similar to this: https://www.headspace.com/
(scroll down mid page to see this)

I am wanting to create it in a shape similar to this with a ball moving inside the letter:

I am wondering if there are visual tools to achieve this, or would it be done purely in code/CSS?

Any suggestions would be great, thanks.

An svg would probably be best and then you could make it responsive but you’d have to draw it and animate it.

For something at a fixed width you could use CSS but may be a bit fiddly to get responsive.

Here’s a start in css for the first part of the M.

You could just repeat that four times (width changes) and then animate the circle up and down. It’s all hard coded though so not the beat approach but I am just out now so haven’t had time to think properly about it.:slight_smile:

SVG is probably the best way to go.

If you want the ball position to depend on the position of its containing element on the screen (as the example you give) use JavaScript. Here is a simple example to show the principle: where the ball’s lateral position is dependent on the container’s position on the screen:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ball in M</title>
<style>
#top, #bottom {height: 100vh;}
#container {width:100vw; height: 15vw ; background: #ff8;}
#ball {position: relative; width:100px; height: 100px; background: #00f; border-radius: 50%}
</style>
</head>
<body>
<h1>Scroll down</h1>
<div id="top"></div>
<div id="container">
  <div id="ball"></div>
</div>
<div id="bottom"></div>
<script>
document.addEventListener("scroll", (event) => {
document.getElementById("ball").style.left = document.getElementById("container").getBoundingClientRect().top + "px";
});
</script>
</body>
</html>

I will leave you to do the mathematics to make it move within a “M” shape :grinning:

1 Like

Here’s a simple svg animation.

Some more information on animating svg and libraries to help.

1 Like

I have now done the mathematics:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ball in M</title>
<style>
#top, #bottom {height: 100vh;}
#container {display: block; margin: auto; width:50vw; height: 30vw ; background: #e3e3e3;}
#ball {position: relative; width:100px; height: 100px; background: #00f; border-radius: 50%}
</style>
</head>
<body>
<h1>Scroll down</h1>
<div id="top"></div>
<div id="container">
  <svg viewBox="0 0 500 300" xmlns="http://www.w3.org/2000/svg">
  <path d="M70 240 L 160 90 L 250 240 L 340 90 L 430 240" stroke="black" stroke-width="90" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
  <circle id="ball" cx="250" cy="240" r="40" fill="white" />
  </svg>
</div>
<div id="bottom"></div>
<script>
let ball = document.getElementById("ball");
document.addEventListener("scroll", (event) => {
let brect = document.getElementById("container").getBoundingClientRect();

// scroll range while container fully in view
let range = window.innerHeight - (brect.bottom - brect.top);

// avoid division by zero
if (range<100) range = 100;

// to get animation while container is fully in view (unless range < 100)
let offset = 180 * (window.innerHeight/2 - (brect.bottom + brect.top)/2) / (range/2);

// limit horizontal movement from centre (SVG viewBox units)
if(offset<-180) offset=-180;
if(offset>180) offset=180;
ball.setAttribute("cx", 250+offset);

// vertical movement each line of "M"
if(offset<=-90) ball.setAttribute("cy", -60-offset*5/3);
if(offset>-90 && offset <=0) ball.setAttribute("cy", 240+offset*5/3);
if(offset>0 && offset<90) ball.setAttribute("cy", 240-offset*5/3);
if(offset>=90) ball.setAttribute("cy", -60+offset*5/3);
});
</script>
</body>
</html>
1 Like

Just playing around with scroll-timeline and it seems that we can get close now without JS.

I haven’t really worked out all the wrinkles yet so just proof of concept.:). Works best on a large window at the moment.

4 Likes

Hi all!

Many thanks for the replies and the help with this, the examples are all fantastic so will have a play around!

Thanks again!

2 Likes