Skip to content
Aman Khalid edited this page Jan 3, 2018 · 2 revisions

Scroll Accordion Animation

Requirements

  • Scroll Magic Link
  • JQuery(Without a doubt)
  • Maths 👽
  • Lodash Link

Step 1

Create a child and parent component in HTML, the child component is the one with animation and the parent is twice the length of the viewport or more. We want to use Scroll magic to make the child stick to the parent's layout.

This creates an effect that makes the user feel like his viewport is fixed, but the parent is in fact scrolling. The background color of the parent must be consistent.

<div class = "parent">
    <div class = "child" id = "child">
    </div>
</div>

main.html

.parent{
    width:100%;
    height:200vh;
    display: block;
}

.child{
    display:block;
    width:100%;
    float:left;
}

style.css

$(document).ready(function(){
    $("#child").stick_in_parent();
});

bring_it_to_life.js

After putting the pieces together, test it out, you should be able to scroll, but it will seem like your viewport is still, also note that if the number of animated slides in your child is more, you can increase the length of the parent.

Step 2: Revenge of maths 🔥

Now that you've set up the scroll magic, its time to work up the real trick. First of all, it is important that the size of our parent must always be greater than the viewport. This will be our surplus length and will not have any contribution to our animation, I'll explain why we need it shortly.

It is much easier to use vh for specifying width and height of the parent in this example, because it sets the height or width with respect to the viewport, if you set the height to 100vh this means the element is as long as the length of the total visible area of the browser.

In this example, I set the height of the parent to be 200vh, which is twice the length of the viewport. Suppose my browser window is 1130 px tall, that means my parent is 2260px tall.

I mentioned earlier that our parent has to be more than 100 vh, so in this example we have 200vh, so we'll use the first half of it as our workspace and let the other half be. Therefore we're left with 2260 - 1130 = 1130 px to work out the calculations.

Screenshot_from_2018_01_03_18_20_03

Now if you have n slides in your animation you divide your workspace into n equal parts. So in this example, each of the 4 slide gets 282 px of the workspace. If your parent is at the beginning of the viewport the first slide will start at 0px and end at 282, the second one will start at 283 and end at 565 and so on. Calculate the starting and ending position of each of the slides and store them as an array of objects in javascript.

[
    {"start":0,"end":282},
    {"start":283,"end":565},
    ....
]

Step 3: Listening 👂👂

Now the only think your code needs is a event listener, a scroll event to be specific. Our aim is to detect the current position of our viewport in px and check that number in our array of objects.

Firstly set an event listener using jQuery $( window ).scroll(function(event) {}). All the calculations are to be made inside the function.

To get the current position of the viewport(More specifically the Y Offset) use this method window.pageYOffset;. This code lives inside the event listener, it calculates the new offset whenever the user scrolls.

After getting the current offset your task is to find where this value lies in our array of objects. Treat the starting and the end position of each slide as a range. Here's a method to it.

_.forEach(array_of_objects, function(value, key) {
				
    if (value.start<=currentOffset && value.end>=currentOffset){
	//Do Something
    }
});

Now that your program can detect where the user is on the viewport and subsequently check whether this position is within one of the slides, YOu can start playing with the DOM.

Step 4: Add and remove class

Here's a little piece of advice for a successful implementation. Never clutter up your CSS, if you don't write modular CSS or do not nest you HTML properly, you will have a hard time animating stuff or even making the site responsive.

The technique whim I'm about to tell is a very basic toggle mechanism. Firstly define how your slides will look when they're not active i.e when the user has not scrolled up to their portion of the workspace.

Now think about your slide when it is active, you may want to increase its height or change its color etc. SO just write down all these changes in a separate CSS class like this. Note that it is not in the class tag of any element yet!

.normal_slide{
   display: block;
   margin: auto;
   float: none;
   width: 150px;
   color: grey;
}
.changed_slide{
    width:300px !important;
    color:red !important;
}

Now in the changed class you do not list all the properties, but only the ones you wish to change with the !important tag to override the default property. So your active slide can look like <div class="normal_slide changed_slide">Hello</div> it has both the classes.

Now in your listener method, which we discussed in the previous step. Trigger the change of class when the condition of checking the range is satisfied. Firstly gather all your slides as an array using var target = $('.normal_slide');.

Listen for the index where condition is met, then change the class in the target array using $(target[current_slice]).addClass( "normal_slide changed_slide" );.

Don't forget to remove the class from your previous acive element before setting the next one. This will finalize your own accordion effect.

Hope you liked this implementation.

Have any suggestions or Questions? Drop me a mail