Jump to content

Pedro Rezende

Horizontal Navigation Bar Movement

Moderator Tag

Recommended Posts

Hi everyone,


I'm working on a unique navigation implementation and could use some guidance. Here's what I'm trying to achieve:


- The navigation items are represented by large vertical bars that correspond to specific sections on the page.

- As the user scrolls and a vertical bar reaches the left side of the screen, it becomes the "current" vertical bar and remains fixed in place.

In my initial attempt, I used a section title as the vertical bar. However, as you can see in the Codepen, I need to have two or more bars anchored to the right side of the screen, moving in sync with their respective sections.

I've added some comments in the Codepen link to explain my thought process, but I'm currently struggling to understand why the bars aren't moving as expected :(


I'm open to suggestions and willing to change the structure I've created if anyone has a better solution to achieve this effect 


Thank you all in advance for your help!




See the Pen bGxyxZG by prznd (@prznd) on CodePen

Link to comment
Share on other sites

Quick thought (not gasp related) but I would probably look at a 3 divs each containing both the relevent sidebar and the panel. You can then play with positioning, either stacking them on top of each other on the left or side by side. Probably easier to animate that way.

Link to comment
Share on other sites

Hello Pedro,


your thought process with regard to that has a couple of issues. But before I start explaining, let me first mention, that your html element for some reason has a height difference of about 16px  in comparison to the body element - I'm not quite sure why exactly that is the case, but it leaves a blank space at the bottom of that amount when the pinning is done, and seems to be to be a CSS styling issue related to your .sidebars__list element. To ommit that, I set the font-size of that element to 0px in CSS in my fork of your example, and instead set a fixed font-size of 16px to the .vertical-bar element. This feels more like a workaround for me though, so that is something you might want to look into.


The first issue I see with regard to your animations, is that you are trying to use xPercent as the property to be tweened on for your scrollTween - that won't work because your individual panels all have different widths. That fake-horizontal-scrolling technique using xPercent will only work when each of your panels has the same exact width of 100vw.


If you want to have different widths for your panels, you would have to tween on the x instead, and calculate things depending on your needs. This in your case can become tricky because of how that example of yours is set up - depending where exactly you want things to end e.g. you will have to incorporate a multiple of the width of your .vertical-bar elements into your calculations (and on top of that the padding-left on your .container - unless you set your elements' box-sizing to border-box).


Additionaly for the calculations (mostly for those coming up) to be precise, you would have to incorporate the width of the browser's scrollbar because of how things are set up (and probably also need to be set up for this to work).


This is the case, because while your vertical bars are positioned fixed so they align with their right side flush against the browser's scrollbar, everything else is dependent on 100vw or window.innerWidth, which both also include the space below the scrollbar in their value. That's why you will see a lot of 15 added or substracted throughout my example, because that's a value that worked fine for my browser with that regard - with different browser's that value might change though, and getting it right throughout all of them can become quite a pain.


Same goes for the ScrollTrigger for your vertical bars - you will need to calculate where exactly to tween them to, when the start of that tween should happen and where it should end; including all things already mentioned in those calculations.


The biggest issue I see in your thought process with ragard to that ScrollTrigger for the vertical bars, is that you want to use the vertical bar as the element to be animated and the trigger element for that animation - that won't work like you might expect because those vertical bars will not move at all, as your scrollTween is not referencing them in any way - it is the horizontal panels that are moving. If you want the bars to move in sync with their respective panel, you should use the respective panel as the trigger element for each bar.


As you can see in the example below, everywhere dynamic values are needed, I make use of function-based values, so ScrollTrigger can get the correct value again when the window gets resized. For start and end of a ScrollTrigger that will work out of the box - for values used for properties of the tween to be invalidated on refresh, too, you will also need to add invalidateOnRefresh: true to the ScrollTrigger.


If I got the description of what you wanted to achieve right, this fork of your example should resemble a setup that would work in a scenario as such.


Although it is quite a bit more complex than you initially thought it might be, I hope this will help clear some things up.

You can read all about the properties mentioned above in the Scrolltrigger docs and general docs for GSAP.


I hope this will help. Happy tweening and scroll responsibly!


See the Pen xxaNyoe by akapowl (@akapowl) on CodePen


  • Like 3
Link to comment
Share on other sites

@akapowl, your reply was absolutely fantastic! Thank you very much. It enlightened me about a couple of conceptual mistakes I was having. Also, great catch regarding the container width proportion. I'll try to implement your suggestions and @The Old Designer's idea as well. I'll get back to you all as soon as I have something working.

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

Hi everyone o/


In the end, I've used the `onUpdate` callback to change sidebar position according to the section movement. It was also tricky to calculate the movement of each section due to their different sizes (thank you @akapowl for pointing that).


I've created a timeline with some labels, which made everything easier to manage and navigate. Also I found the function labelToScroll which helped a lot to handle the sidebar links. It was important because we're gonna add more contents as soon as the event info get released, so it will be a combination of a virtual vertical and horizontal scroll. So `labelToScroll` worked perfectly for pointing the browser scroll to the correct position.


Thank you all for the insights!


  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.