Site logo

Archived topic

Sticky second navigation

36 replies · Started by nik9 on January 7, 2021

Viewing posts 16–30 of 37

Must that be implemented in the script or what’s wrong with my CSS?

You should remove all the CSS that adds styles and let the JS add/remove position: sticky; and top: 85px;.

So if the user scrols and the main nav is not visible it should be top: 0.

Check which state this is in. If it's before sticky-navigation-transition then add a condition for the before transition state and add in that styling.

Hi Elvin,

I already tried this. But I never get the log "stickyNavTransitioned". Its always "scrolling up" or "not transitioned". I already tried to work wirh "is_stuck" and not "is_stuck". No change.. The Hooks is selected for wp_footer. Is there maybe a issue?

<script>
const stickyNav = document.querySelector('nav.main-navigation');
const secondaryNav = document.querySelector('nav#secondary-navigation');

var lastScrollTop = 0;

// element should be replaced with the actual target element on which you have applied scroll, use window in case of no target element.
document.addEventListener("scroll", function(){ // or window.addEventListener("scroll"....
   var st = window.pageYOffset || document.documentElement.scrollTop; // Credits: "https://github.com/qeremy/so/blob/master/so.dom.js#L426"
   if (st > lastScrollTop){
      if(stickyNav.classList.contains('sticky-navigation-transition')){
				var stickyNavTransitioned = document.querySelector('nav#sticky-navigation');
				console.log("stickyNavTransitioned");
				secondaryNav.style.position = "sticky";
				secondaryNav.style.top = '85px';
			} else if(stickyNav.classList.contains('sticky-navigation-transition') == false){
				console.log("not transitioned");
			}
   } else {
			console.log("scrolling up");
   }
   lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
}, false);

</script>

Hi Elvin,

Now it looks way better!

I also added a secondaryNav.style.transition = "1s";. Its working. But looks not nice because the second nav is visible when the main nav faded in. So I now try to animate the second nav fadein with opacity.

fadein {
    from { opacity: 0; }
    to { opacity: 1; }
}

Do I have to add this in the script on in a CSS? I guess the thing here is that is only should fire if we scroll down. Currently is also fire by scroll to top.

<script>
const secondaryNav = document.querySelector('nav#secondary-navigation');

var lastScrollTop = 0;

// element should be replaced with the actual target element on which you have applied scroll, use window in case of no target element.
document.addEventListener("scroll", function(){ // or window.addEventListener("scroll"....
		var st = window.pageYOffset || document.documentElement.scrollTop; // Credits: "https://github.com/qeremy/so/blob/master/so.dom.js#L426"
		var siteNav = document.getElementById('sticky-navigation');
		if (st > lastScrollTop){
      if(document.contains(siteNav)){
				if( siteNav.classList.contains('sticky-navigation-transition') ){
					var sn_height = siteNav.offsetHeight;
					console.log(sn_height+"stickyNavTransitioned");
					secondaryNav.style.position = "fixed";
					secondaryNav.style.top = sn_height+'px';
					secondaryNav.style.transition = "1s";
				}
			} else if( !siteNav.classList.contains('sticky-navigation-transition')){
				console.log("not transitioned");
			}
		} else {
			console.log("scrolling up "+st);
			if(window.scrollY==0){ 
			 	console.log("Top of page");
				secondaryNav.style.position = "relative";
				secondaryNav.style.top = "0px";
				secondaryNav.style.transition = "0";
			}
		}
	
		lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
}, false);

</script>

fadein {
from { opacity: 0; }
to { opacity: 1; }
}

You can add this fadein class to the secondary nav when it is in sticky state. Just make sure to remove it when it's back to the top so it toggles.

Something like this:

<script>
const secondaryNav = document.querySelector('nav#secondary-navigation');

var lastScrollTop = 0;

// element should be replaced with the actual target element on which you have applied scroll, use window in case of no target element.
document.addEventListener("scroll", function(){ // or window.addEventListener("scroll"....
		var st = window.pageYOffset || document.documentElement.scrollTop; // Credits: "https://github.com/qeremy/so/blob/master/so.dom.js#L426"
		var siteNav = document.getElementById('sticky-navigation');
		if (st > lastScrollTop){
      if(document.contains(siteNav)){
				if( siteNav.classList.contains('sticky-navigation-transition') ){
					var sn_height = siteNav.offsetHeight;
					console.log(sn_height+"stickyNavTransitioned");
					secondaryNav.style.position = "fixed";
					secondaryNav.style.top = sn_height+'px';
					secondaryNav.style.transition = "1s";
					secondaryNav.classList.add('fadein');
				}
			} else if( !siteNav.classList.contains('sticky-navigation-transition')){
				console.log("not transitioned");
			}
		} else {
			console.log("scrolling up "+st);
			if(window.scrollY==0){ 
			 	console.log("Top of page");
				secondaryNav.style.position = "relative";
				secondaryNav.style.top = "0px";
				secondaryNav.classList.remove('fadein');
			}
		}
	
		lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
}, false);

</script>

I basically just added secondaryNav.classList.remove('fadein'); and secondaryNav.classList.add('fadein');.

Hi Elvin,

I understand. Now I made tests with this:

@keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

But its not nice. So I want actually the same fade in like the main navigation on sticky. To get that, I tried to use the sticky-navigation-transition class in secondaryNav.classList.add('sticky-navigation-transition'); But that does not work. Is it another class?

Tom is using jQuery's fadeIn() for this. It's set to fadeIn(300).

You can try to add in the function created here to have something similar with Vanilla JS:
https://stackoverflow.com/a/30206184

You then change secondaryNav.classList.add('fadein'); to _('secondary-navigation').fade('in', 300); but I'm not exactly sure how well it would work or if it would work at all.

Ok Thanks. So there is no option to add styles direct in this part (CSS) without vanilla function? I mean, when I add a CSS class like fadein and give them some fade option, then it should work? Or what do I miss here?

.fadein {
animation: fadeIn ease 20s;
-webkit-animation: fadeIn ease 20s;
-moz-animation: fadeIn ease 20s;
-o-animation: fadeIn ease 20s;
-ms-animation: fadeIn ease 20s;
}

secondaryNav.classList.add('fadein');

Ok Thanks. So there is no option to add styles direct in this part (CSS) without vanilla function? I mean, when I add a CSS class like fadein and give them some fade option, then it should work? Or what do I miss here?

It's possible but then again, you're trying to match the fadeIn done by the primary sticky nav.

If you want to go ahead and use the CSS route, change the animation property values a bit.

20s is too long. Try fadeIn ease-out 0.3s;

Perfect!

Last thing: When I scroll now down (just a little bit), then the second nav is not at the top from the page. When I change the header size to 100px instead of 85px, then the nav is at the top when the main nav is not visible becasue of scroll. I guess for that I have to adjust the script?

I'm not sure what adjustment to apply that will look good.

That state you see when you scroll a bit is the "inbetween" state between sticky and the default position attribute. It's when the site-navigation and secondary-navigation is prepped but is yet to be fully sticky.

Putting the second nav to the top of the page means you'll have to make it overlap it with the primary nav which will look weird.

I personally would rather make them immediately put them both on opacity: 0; on the "inbetween" state rather than doing that.

Ah okey. Make sense!

the "inbetween" part is this one right?

else if( !siteNav.classList.contains('sticky-navigation-transition')){
	console.log("not transitioned");
}
<script>
const secondaryNav = document.querySelector('nav#secondary-navigation');

var lastScrollTop = 0;

// element should be replaced with the actual target element on which you have applied scroll, use window in case of no target element.
document.addEventListener("scroll", function(){ // or window.addEventListener("scroll"....
		var st = window.pageYOffset || document.documentElement.scrollTop; // Credits: "https://github.com/qeremy/so/blob/master/so.dom.js#L426"
		var siteNav = document.getElementById('sticky-navigation');
		if (st > lastScrollTop){
      if(document.contains(siteNav)){
				if( siteNav.classList.contains('sticky-navigation-transition') ){
					var sn_height = siteNav.offsetHeight;
					console.log(sn_height+"stickyNavTransitioned");
					secondaryNav.style.position = "fixed";
					secondaryNav.style.top = sn_height+'px';
					secondaryNav.classList.add('fadein');
				}
			} else if( !siteNav.classList.contains('sticky-navigation-transition')){
				console.log("not transitioned");
			}
		} else {
			console.log("scrolling up "+st);
			if(window.scrollY==0){ 
			 	console.log("Top of page");
				secondaryNav.style.position = "relative";
				secondaryNav.style.top = "0px";
				secondaryNav.classList.remove('fadein');
			}
		}
	
		lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
}, false);
</script>

Yes that's it but I'm not exactly sure if its working well. I've focused mostly on making the actual sticky work that I've yet to play around properly with that condition.

But yeah, if it works, that's where I'd put it so it hides on the inbetween state.

I understand. But I get a Error (index):4722 Uncaught TypeError: Cannot read property 'classList' of null in that inbetween state. So I guess that's why it does not work currently with

} else if( ! siteNav.classList.contains('sticky-navigation-transition')){
console.log("not transitioned");
				
secondaryNav.style.opacity = "0";
				
}

Can you try changing this:

else if( !siteNav.classList.contains('sticky-navigation-transition')){
				console.log("not transitioned");
			}

To simply this:

else{ 
	console.log("not transitioned"); 
	secondaryNav.style.opacity = "0"; 
}

And check if it works?

This archived topic is closed to new replies.