Sticky navigation starting at special point

Hello there!
Sorry if my English is not perfect, I’m from Germany.
I’ve been working with Hype for two months now, working on my bachelor project. Now my question: I added a sticky navigation to my website which appears at the top of the page as soon as the page is fully loaded. So far, so good. But I would prefer the navigation to appear later on the page when you scroll down, like in this example:
-> http://www.itsmassive.com

So far I worked with this code:

lastPos = {
y1 : 0,
y2 : 0
}

el = hypeDocument.getElementById('header');
sPos = el.getBoundingClientRect().top;

window.onscroll=function(){
wY = window.pageYOffset || (document.body.scrollTop || document.documentElement.scrollTop) ;
lastPos.y1 = lastPos.y2; lastPos.y2 = wY;

if(wY >= sPos && c){
c = false;
el.style.top = '0px';
el.setAttribute("class","sticky");
}

if (lastPos.y2 < lastPos.y1 && wY <= sPos && !c){
c = true;
el.style.top = sPos + 'px';
el.setAttribute("class","");
}

}; 

I already tried to change the positions but as I’m not that used to coding it didn’t work out the way I wanted it to - means: after I changed the positions it didn’t work out at all anymore, the navigation appeared on top but was not sticky anymore.
Maybe someone can tell me what I have to change to make it work?
I would be so grateful! :grin:

PS: I added the original sticky navigation file
sticky-nav.hype.zip (211.3 KB)

somehow adding a zip of my .hype document isn’t possible… I can upload it, but as soon as it is at 100% it isn’t shown anymore… don’t know what I’m doing wrong here…

  • It’d be useful to attach a zip of your .hype document, that way anyone helping does not need to recreate the page with assumptions that may be built into your code.
  • It’d be good to elaborate on “didn’t work out the way I wanted it to” as we won’t know what you may be going for either.
  • if that code comes from a specific source it’d be good to link to that
  • small note: when posting code on the forums, generally you’ll want to surround it in a triple-tick ( ``` ) block so that it retains its originally formatting
1 Like

Thanks for your advices, I will change my post and add the infos :slight_smile:

@melimascella

Hi Melina!

I already created the following before You posted an example… if there is something here You can use great!

Hype Demo project: Scrolling - movable FixedMenu_JHSv3.hype.zip (25.6 KB)

I went for a simple approach and started from scratch rather than adjust your code. All the work is done in the Demo by the function “scrollToFixedMenu” (which follows).

I use “scrollY” to establish where we are on the page (like your use of “scrollTop”) and if we go above (or under) a certain number then we set the properties for the element (ID “menu”) accordingly.

    menuToFixed = hypeDocument.getElementById('menu');
	window.onscroll = function() {
		if (scrollY > 245) {
		    menuToFixed.style.position = "fixed";
		    menuToFixed.style.top = "0px";
		  	} else { // we are close to the top so switch styles
		  	menuToFixed.style.position = "absolute";
		  	menuToFixed.style.top = "245px";
		  	menuToFixed.style.left = "auto";
		  	menuToFixed.style.right = "auto";
		}
	}
5 Likes

Thanks a lot, it is working now! :slight_smile:

1 Like

oh, this is great.

But what about if scrolly >800, and make the menu unfixed? how should rewrite this JS please?

Hi Alex!

You would simply include another conditional in the code for the "scrollY > 800"...

Scrolling - movable FixedMenu_JHSv5.hype.zip (23.9 KB)

Note that when the "Menu" is set to "absolute" positioning for "scrollY > 800" we also set the "top" property to "800px" so it scrolls out of view smoothly it doesn't suddenly disappear.

menuToFixed = hypeDocument.getElementById('menu');
	
	window.onscroll = function() {	
		if (scrollY < 245) {
	    menuToFixed.style.position = "absolute";
	    menuToFixed.style.top = "245px";
	    menuToFixed.style.left = "auto";
	  	menuToFixed.style.right = "auto";
	  	} else if (scrollY > 245 && scrollY < 800) {
	    menuToFixed.style.position = "fixed";
	    menuToFixed.style.top = "0px";
	    menuToFixed.style.left = "auto";
	    menuToFixed.style.right = "auto";
	  	} else if (scrollY > 800){
	  	menuToFixed.style.position = "absolute";
	  	menuToFixed.style.top = "800px";
	  	menuToFixed.style.left = "auto";
	  	menuToFixed.style.right = "auto";
		} 
	}

Great thanks.

It works great well.

What about if make images WITH ANIMATION work as this way when scroll the page.

and here is the animation Javascript:

window.onscroll = function () {
	
	var scrollAmount = scrollY;
	hypeDocument.goToTimeInTimelineNamed(scrollAmount * 0.006, 'timeline1')
	hypeDocument.goToTimeInTimelineNamed(scrollAmount * 0.006, 'timeline2')

}

and aslo, I used your javascript as:

menuToFixed = hypeDocument.getElementById('image');

window.onscroll = function() {	
	if (scrollY < 3736) {
    menuToFixed.style.position = "absolute";
    menuToFixed.style.top = "3736px";
    menuToFixed.style.left = "auto";
  	menuToFixed.style.right = "auto";
  	} else if (scrollY > 3736 && scrollY < 3882) {
    menuToFixed.style.position = "fixed";
    menuToFixed.style.top = "0px";
    menuToFixed.style.left = "auto";
  	menuToFixed.style.right = "auto";
  	} else if (scrollY > 3882){
  	menuToFixed.style.position = "absolute";
  	menuToFixed.style.top = "3882px";
  	menuToFixed.style.left = "auto";
  	menuToFixed.style.right = "auto";
	} 
}

unfortunately, they does not work at the same time, is it possible to make these two javascript work at the same time?

here is the Hype document:scrollfixoncondition.hype 2.zip (22.2 KB)

it would be great appreciated if you could let me know what I should do, thanks again.

I don’t have time in the immediate future to work with this - but it seems that an element with a “position = fixed” property, that is also scaling, might work at cross-purposes… don’t know as I haven’t tried something like this before.

Another approach would be - for the element that is scaling - to have its “top” property continually increasing in value (i.e. it is moving down the page); so while the element is being moved down - the overall appearance, because it is also being scaled up - has the effect of making the element look static, or “fixed” in position.

Of course, You have to precisely balance the increase of the scaling of the element to the increase of the “top” property value otherwise the element will jitter. Clearly some trial and error will be needed to find the right mix.

Yes, it is just what I mean here. it is easy to make a element work on several timelines at same time, but it is seems difficult for me by JS.

I tried that, and it looks not so smoothly.

Alex

Hi Alex!

Sorry for the delay but this has been my first opportunity to reply…

Hype Demo Project: Scrolling - movable FixedMenu_JHSv7.hype.zip (23.8 KB)

This project uses JavaScript only - no timelines. I have checked this demo on Safari, Chrome, Firefox & Opera (all Mac) - all work.

When viewing this project please resize your browser window so just the first three bars are showing. This will allow the last change in positioning (back to “absolute”) to clearly display without an overly long page height needed. In your actual project You can make it any length You wish of course. (Please see Fig.1 below).

Fig.1
BrowserWindowSize


Overview
As the viewer scrolls the page down the “target element” (absolute positioning) scrolls into view. At a point a few hundred pixels below the top of the browser window the target element assumes a “fixed” position and scales up in size.

With further scrolling (several hundred pixels) the target element is re-assigned the “absolute” positioning and scrolls out of view.


Details

Here is the code for the function (triggered by “On Scene Load”):

var elToFixed = hypeDocument.getElementById('targetEl');
var elReadOut = hypeDocument.getElementById('elementReadout');
	
	window.onscroll = function() {	
	elReadOut.innerHTML = scrollY;
	if (scrollY < 800) {
	    elToFixed.style.position = "absolute";
	    elToFixed.style.top = "1100px";
	  	} else if (scrollY > 800 && scrollY < 1300) {
	  	elToFixed.style.position = "fixed";
	  	elToFixed.style.top = "300px";
	  	elToFixed.style.left = "auto";
	  	elToFixed.style.right = "auto";
	  		if (scrollY < 950){
			hypeDocument.setElementProperty(elToFixed, 'scaleX', (scrollY - 699)*.01);
			hypeDocument.setElementProperty(elToFixed, 'scaleY', (scrollY - 699)*.01);
			}
		} else if (scrollY > 1300) {
		elToFixed.style.position = "absolute";
	    elToFixed.style.top = "1600px";
		}
	}

You will note there are very specific numbers used in this code. To make it easier to figure out what these numbers should be - particularly “scrollY” I have inserted:

var elReadOut = hypeDocument.getElementById('elementReadout');

elReadOut.innerHTML = scrollY;

This code places the “scrollY” readout in the target element (id “elementReadout”) - as you scroll this number is constantly updated. (Please see Fig.2 below.)

Fig.2 - “scrollY” readout
innerHTML_Readout


The Scaling of the Target Element

The scaling is controlled by the scrolling - not a timeline. As mentioned before we are not using timelines in this demo.

if (scrollY < 950){
    hypeDocument.setElementProperty(elToFixed, 'scaleX', (scrollY - 699)*.01);
    hypeDocument.setElementProperty(elToFixed, 'scaleY', (scrollY - 699)*.01);
}

The number “699” is based on the scrollY trigger of “800” (which sets the target elements position to “fixed”). I wanted to come up with the number “100” - which when multiplied by “.01” yields a one percent scaling for every pixel scrolled. You will notice that “800-699” = “101” not “100”… BUT the on-screen scaling worked smoother using “101” instead of “100”.

All these numbers will be variable depending on when the “conditional” code is needed to be triggered for your particular project - so You will no doubt need to make adjustments.

1 Like

Hi @JimScott,

Thanks for your great work, it looks really charming:)

I understand that there are several parts:

absolute
    <800
fixed
    >800,<1300,
scale
    >800<950,
scale complete
    >950 
change back to absolute.
   >1300

Yes, so I am just thinking that it would be even more great if you could also make support scroll timelines, so that it support much more elements and animations at a fixed position, not only one element scaling. is it possible please?

Thanks again, and have a nice day.

Alex

I followed up with your original request (quoted just above) to use JavaScript to manipulate an element in this regard. Your original example showed just one element scaling and changing position properties:
scrollfixoncondition.hype 2.zip (22.2 KB) - so that's what I created for You.

Yes, so I am just thinking that it would be even more great if you could also make support scroll timelines, so that it support much more elements and animations at a fixed position, not only one element scaling. is it possible please?

You have all the information You need to accomplish your newest request right here in this thread. I am done.

1 Like

Hi @JimScott,

I see, really thanks, great work:)
As to timelines scroll, I am not technical background, and that is just what I was thinking.

Have a nice day.

1 Like

Oh Alex - come on - You give up too easy!

The following is not technical. You already had all the examples You needed - just cut & paste.

In the “onScroll” section I added the following two lines to my previous demo project (_JHSv7):

window.onscroll = function() {	
	var scrollAmount = scrollY;
	hypeDocument.goToTimeInTimelineNamed(scrollAmount * 0.006, 'Animate1');

You’ve seen this code before in this thread.


In the attached Hype Demo (_JHSv8) I also added a timeline called “Animate1” to match the new code.

This timeline rotates the target element & then changes its color.

Simple!

Now I’m done - this time I mean it! :sunglasses:

Scrolling - movable FixedMenu_JHSv8.hype.zip (24.2 KB)

3 Likes

:grin::grin:

ok, I will challenge more next time :grin:

Really great work, thanks.

sometimes, I do not know how to achieve an animation, and sometimes, I do not know how to say that exactly in English even I know, sorry for my poor english.

After view your great demo, at the beginning, I realize that I should say: Scrolling timelines at a fixed position, right? :slight_smile:
Thanks again, and have a nice day.

Alex

1 Like

Hello @JimScott

What about if I need trigger multiple Element ids, I tired these ways, but not work for me:

First way:

var elToFixed = hypeDocument.getElementById('targetEl1' 'targetEl2' targetEl2');

Seond way:

var elToFixed = hypeDocument.getElementById('targetEl1');
var elToFixed = hypeDocument.getElementById('targetEl2');
var elToFixed = hypeDocument.getElementById('targetEl3');

Thanks

1 Like

Hi Alex!

I don’t have a lot of time right now to create a working example with my code above but I would think an array would be a good approach for this situation.

You can read about arrays here. Look down this page for the sub-head “Looping Array Elements”.

I will not be available in the immediate future for any follow-up questions - so hopefully this will do the trick for You - or someone else may help or have a suggestion.

Hi Jim,

Thanks anyway, that is definitely a great way.

By the way, I found the way of triggering by Unique Element ID might be quite limited, and the way by class name seems quite flexible.

and I am just thinking the possibility of the way of changing "fixed" to absolute" and absolute to fixed by hypeDocument.setElementProperties, and I found an interesting case here:

and I will study more, and thanks again.

Indeed - Class allows for greater freedom in a multiple use scenario...

Glad your studies are bearing fruit! :+1::cherries::strawberry: