Draw line animation on scroll using transform: translate3d and JS

I’m trying to recreate this effect on the site I’m working on now.
Here’s the site.

The one where it looks like it’s drawing a white line towards the next element when scrolling and would shorten when it has reached that element and the user still continues to scroll.

I really have no idea what’s going on. All I know is that it does not actually draw a white line and it’s using transform: translate3d.

I’m researching for a few days now but most search results include parallax and svg which I don’t think is what I need to do this (I’m not sure) and the remaining results aren’t what I need either.

If anyone can explain how the animation works, that would be a huge help.
Thank you so much.

P.S. I’m sure the title of my post is a bit off so if anyone can edit it for me, that would be nice. Thank you in advance.


It looks to me as though its a 1px div with a white background that has its position and height adjusted dynamically via js to match the scroll position while inside a 50vh parent container.

This is the basic element:

#product-tour .tour-stroke .stroke-inner {
    background-color: #fff;
    margin-right: auto;
    margin-left: auto;
    width: 1px;
    height: 100%;

Its offset in a container that has a 50vh height to keep the images apart.

#product-tour .tour-stroke { 
position: relative;
    overflow: hidden;
    width: 80px;
    margin: 40px auto;
    z-index: 200;

The rest is js to animate the positoin of the white line using transform:translate.

If we colour the outer container red you can see how the white line is animated from outside the red box (overflow:hidden hides the white line) until it meets the bottom of the red box and then continues until it disappears through the bottom of the red box.

I’m not around for most of the day otherwise I would have played around with it although my js skills are limited.

The basics of what you need are a container that is 50 vh tall with overflow:hidden. Inside that container you have a 1px container with white background that is 100% of the parent tall (e.g. the same height). You start with the white line transformed out the top of the container so it is invisible.

When the window scrolls and the red box is at xx% of the viewport you start animating the white line from top to bottom using translate as mentioned until it disappears out the bottom of the red box. (Obviously vice versa when you scroll up).

Hopefully that is some help:)

If I get a chance later I will set up the css for the boxes and then you can investigate adding js on scroll etc.

1 Like

This is a great help!

Thanks for taking the time to explain this. I understand how it works now.

I have a question, though. This may be dumb but when the white line is out of the container and the user keeps on scrolling, where does the white line go? Does it keep on moving down as the user scrolls down?

Thank you so much, @PaulOB. :blush:

If you look in dev tools it seems that the line just keeps getting animated with the scroll position. It is of no importance because the ‘red’ container is overflow:hidden. As the red container comes back into the viewport then so will the white line as it is constantly animated in line with the scroll position.

At least that’s my take on it. I suppose the line could have been stopped animating once it was outside the red box but then I guess you have to re-check when it has re-entered that area. At the moment it does’t seem to need to know where the box is located as it is just continually transformed up and down but only becomes visible once inside the red box.

Hmmm, I’m wondering of perhaps a similar effect could be achieved using a fixed background image of a white line instead. Have to rush out soon but hopefully you can make a start.

1 Like

I understand now.

My knowledge in coding is very limited so I still don’t know how to implement this but at least I now know where to start. Thank you so much for this. Take care!

Here’s a very very very rough example of using a fixed background image for the line.


The code is all in the page so just view source. It’s not as neat as the js controlled example but is all css. I;m sure it could be tidied up a bit to look better.

Obviously your original example doesn’t fade in the images until they are in the viewport which gives that better effect. there are some css libraries that can help with that if you need help.

I am definitely out the door now :slight_smile:

1 Like

Hey, @PaulOB!

This is great! :scream: Thank you so much. You are so cool.

1 Like

I added a small fade in effect for the blocks using in-view.js.


Codepen example:


Hi, @PaulOB! Thank you so much for this.
You are helping me a lot.

I tried this on Firefox and Edge but the white line doesn’t seem to move in those browsers.
Not really sure why. This is the first “real” website I’m working on so this is also the first time I’m checking my work on different browsers.

I just tried Paul’s demo in Chrome and Firefox. The white line behaves the same (changes length and moves) in both.

1 Like


Yes the problem in Firefox is that the transform property kills the ‘fixed attachment’ as it creates a stacking context when it shouldn’t (some say this is not a bug but a behaviour but it really is an unwanted behaviour and a pain in the neck).

Edge had a different bug with not liking a 1px width (probably dues to rounding error in Edge) so the width needs to be greater than 1px for the line holder element.

i.e Remove the transform from the following rule and set the width to 3px instead of 80px.

.join {
	height:calc(50vh + 60px);
	position: relative;
	overflow: hidden;
	width: 3px;/* greater than 1px for edge bug*/
	margin: -30px auto;
	z-index: 200;
	background:url(images/whitebgline.gif) no-repeat fixed 50%;
	background-size:1px 70vh;
	/*transform:translateX(50%); remove as creates stacking context for fixed positioned image*/

That should fix it.

However I notice that edge scrolls very badly with the fixed positioned element attached to the :after element so I have removed it and applied it to the body as per normal but included a script snippet for touch devices that re-instates the :after element. (Note that the squarespace link you showed in your first post suffers badly in Edge with jumping when scrolling with the mousewheel although this may be device/mousewheel specific also)).

IOS does not work with fixed attachments and background-size:cover which is why they need a separate fixed element and normal background-attachment to work.

Note also I have just set the white line on touch devices to be of fixed height as they won’t scroll it properly anyway.

IE11 doesn’t work with the js arrow functions so I have removed them.

There may be other bugs as this is just a proof of concept but I have update the link and the codepen which should work in IE11, Edge, Chrome & Firefox now.



I probably just updated it :slight_smile: (sorry)

1 Like


It’s working perfectly now but I have a few problems when I’m trying to implement it on the site I’m making.
Mind if I dm you a link to the site and check what I’m doing wrong?

Thank you so much for all of your help.

Yes ok PM me the link and I’ll take a look.

It may be Sunday before I can look properly as I am out and about today :slight_smile:

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.