On my site, I have two Navigation Bars, one scrolls up along with the text but the other hides when I scroll up and shows when I scroll down. I just don't know how to make it invisible once it's back to pageYOffset = 0. Anyone knows how, please?
first, welcome to stackoverflow!
to know when the offset is at a particular position, you need to listen for the scroll and resize events, try something like:
function checkPageOffset() {
if(window.pageYOffset === 0) {
// do your menu manipulation here
}
}
window.addEventListener('scroll', checkPageOffset);
window.addEventListener('resize', checkPageOffset);
this way, the function runs on each scroll and each resize and only runs code if the offset is 0. you may prefer to test window.pageYOffset < someMinimumOffset instead in case the scroll is not exactly to 0.
as i was getting at with my comment above, chances are there's already code somewhere in your system that's testing if the offset is greater than some threshold in order to display the menu in the first place, really you should just have to add on to that function to hide the menu if that condition is not met. if you can post that code, we might be able to help you integrate a solution more cleanly with your existing setup.
edit: incorporate listen for resize as per Tracker1's comment below
Related
I am trying to add a class to my sticky container once the user scrolls the page past 100px, but it is lagging, and toggling the class uncontrollable.
$(function () {
$nav = $(".topmenu-container");
$(document).scroll(function () {
if ($(this).scrollTop() >= 100) {
$nav.addClass('scrolled');
} else {
$nav.removeClass('scrolled');
}
});
});
This is what I have so far.. I had the same function without an if clause and the toggleClass function instead, but same effect there.
Here you see the container that sticks to the top on scroll, and that I want to add the class to once the user scrolls past 100px from top for example
Edit: I now output the scrollTop value and saw, that it seems to get stuck at the point where the toggle should happen. It keeps jumping between 156px and 87px which makes the toggle happen multiple times a second. Does anyone have an idea?
What you need is rate limiting for your scroll events. In your case, I would suggest throttling, which means that your scroll events are limited to a certain number per second or time unit.
Another option is to use debouncing, but this would cause the event to be triggered only once at the end of the scrolling, which might not be the best solution for your case.
Read more here: Difference Between throttling and debouncing a function
Nice visualization: http://demo.nimius.net/debounce_throttle/
Depending on your use case you may actually get away with the new sticky value for the position property in CSS:
https://developer.mozilla.org/en-US/docs/Web/CSS/position
Additionally, instead of using debouncing and throttling, you could consider using the IntersectionObserver API. The events for InteresectionObserver fire only once (depending on settings) and surely less than scroll which is a hard to optimize event since it fires all of the time. See here:
https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
Now, if you have some elements inside the element that depend on the class, such as... the logo having a scaling animation or such, you will definitely have to use IntersectionObserver. It looks like your threshold is 100 pixels, you can definitely configure Interesction Observer to do that.
You can also take a look at this example from Wes Bos which seems to be in one of his free classes:
https://wesbos.com/javascript/06-serious-practice-exercises/scroll-events-and-intersection-observer
I'm hoping you can try these solutions instead of the antiquated scroll thing.
I want to build a portfolio side similar to this one. Only a little bit more a beginners version. But with the same concept.
www.rleonardi.com/interactive-resume/
Is the anyone who know how I can scroll sideways where the y scroll-bar is used?
And I have another question ? where can I read about those skills and/or practice?
He basically uses a onscroll event handler in which he detects the y value (scrollHeight) and sets/moves/displays/hides/etc objects on specific y values. The page is just scrolling down, but the elements are moved in. So it looks like horizontal scrolling, but it's not. It's elements moving from right to left, etc.
(A lot of (very fine!) work by the author.) Have a closer look at:
window.onscroll = function (e)
{
if (canScrollOrSwipe == true) //to avoid user swipe when window is still resizing after screen orientation changed on table
{
detectPageVerticalPosition();
runTheseFunctionsAfterScrollOrSwipe();
}
}
And the functions called there.
Or better yet: contact this webdesigner himself before copying :)
I'm having a problem implementing relatively complicated auto-scroll functionality on my page. This displays the issue in my code...
http://codepen.io/d3wannabe/pen/XXxdQq
I have multiple divs on my page (blue,red,green in my example) that I not only want to be able to scroll to (which the top 3 buttons in my example achieve perfectly), but I want to be able to scroll WITHIN (which the bottom 3 buttons represent my best attempt at).
The thing I can't figure out, is why the scroll within function works well on my first div ("scrollTo3rdBlueItem" button), but then less accurately with the other divs ("scrollTo3rdRedItem" and "scrollTo3rdGreenItem" buttons). In my full web application (which obviously has more data to scroll through), I basically see that the lower down the page the parent div is positioned, the less accurately I'm able to scroll within it.
I'm struggling to identify much of a pattern though so can't simply try tweaking the offset values. Any ideas what I might be doing wrong here would be hugely appreciated!!
...since I wasn't allowed to post this without quoting code - here's the jquery function you can see in my codepen!
function scrollToParent(parentID){
$('html,body').animate({scrollTop: $('#'+parentID).offset().top}, 500);
}
function scrollToChild(parentID, childID){
//first focus on the parent
scrollToParent(parentID);
$('#'+parentID).animate(
{scrollTop: $('#'+ childID).offset().top - 100}
, 500);
}
UPDATE
Answer here was COMPLETETLY wrong. Left here to preserve the comments.
UPDATE 2
Got IT! You need to take in to account the offset of the parent div. Update your scrollToChild function to the below;
$('#'+parentID).animate(
{
scrollTop: $('#'+ childID).offset().top - $('#'+parentID).offset().top
}, 500);
I've been racking my brain and my Google Fu for a few hours now trying to find a solution to this one, but can't seem to come up with anything satisfactory.
I want to affix an element to the side of the page for some search criteria, much like Bootstrap's "Affix" plugin. (Demo Here). The problem is that it's going to be very common that the element is much taller than the window. So there will be scrolling of the element itself involved.
Usually this wouldn't be a problem because as the user hits the top + bottom of the document they would be able to see the top and bottom of the fixed element. (See bootstrap example while shrinking you're window very short). But we're planning on using infinite scroll on our results set, meaning there won't be a bottom to hit, and therefore they'll never see the bottom of the fixed element. As the user scrolls down, it needs to be bottom fixed so the user sees all criteria, then on the way up, it needs to be top fixed.
So I started off by modifying Bootstrap's plugin (I'm not actually using bootstrap). Now scrolling down the page is easy, using a fixed point on the bottom of the element means that it's not affixed until you reach the bottom of it.
But scrolling back up again is where I'm hitting issues.
Am I missing something really obvious and easy here (it is Monday morning after all), or does anyone know of a plugin / patch to bootstraps affix.
TL;DR
Need to affix a very tall element to the page and allow it to scroll. So it's fixed on the way down, then as they scroll back up, the element isn't fixed so it's also being scrolled up. Once the top of the element is hit, fix it there.
Is this what you Want to do DEMO
Simple jQuery function that will help.
$(function()
{
affix= $(".affix-top");
var affixHeight = parseInt(affix.height());
var affixTop = parseInt(affix.offset().top);
var affixBottom = parseInt(affixTop + affixHeight);
// Bind a scroll event for the whole page
$(document).bind("scroll", function(e)
{
// Calculate how far down the user has scrolled
var screenBottom = parseInt($(window).height() +$(window).scrollTop() );
// Test if the div has been revealed
if(screenBottom > affixBottom)
{
affix.attr("style","");
affix.css({"bottom":"0px","position":"fixed"});
}
else
{
affix.attr("style","");
affix.css({"top":"0px","position":"relative"});
}
});
});
I've Googled for this but must be using the wrong keywords.
Basically I want to use the effect that Magento and now Stack Overflow uses. That is, there is an element in a column, and when you scroll down, it sticks to the top of the viewport. And once scrolled up again, it goes back into the normal page flow.
This Ask A Question is a good page for example. Scroll down and watch the "How to Format" element come down (might need to make your viewport smaller if you have a large screen to see the effect).
I've noticed it is setting position: fixed in the CSS. The JavaScript however is obfuscated.
What's the easiest way to achieve this effect? Is there a jQuery plugin available?
Here is an article that should help: http://www.wduffy.co.uk/blog/keep-element-in-view-while-scrolling-using-jquery/comment-page-1/
I noticed google doing this in certain places, like here http://news.google.com/nwshp?hl=en (the left side navigation bar). From what I can tell, they checking the position on the page and then setting the item to a fixed position once the page is scrolled down enough for the element to start scrolling off the screen.
It looks like the other method, using jQuery to set the top margin will allow the element to lag behind and get choppy (if you don't use animation) since the javascript must continue to position the element.
Here is an example in Ext, it would probably help a lot if I didn't have the select in the event handler, but it works.
Ext.fly(document).on("scroll", function(e,t,o){
Ext.select(".pinnable").each(function(el,c,idx){
var y = window.scrollY;
if(!el.hasClass("pinned")){
var ypos = el.getY();
if(y>ypos){
el.addClass("pinned");
el.set({
originalY:ypos
});
}
} else {
var origy = el.getAttribute("originalY");
if(origy && y<origy){
el.removeClass("pinned")
}
}
});
});