I am editing a site that has a sticky footer #sticky-footer-wrap this div has the CSS properties position: fixed; bottom: 0; so it hangs at the bottom of the page.
Once the user scrolls to the bottom of the page, the full size, expanded footer #exp-footer is displayed and #sticky-footer-wrap is hidden.
This is the JS I am currently using:
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() == $(document).height()) {
$('#sticky-footer-wrap').hide();
$('#exp-footer').show();
var scrollY = $('body').scrollTop()?$('body').scrollTop():$('html').scrollTop();
$('html, body').animate({
scrollTop: scrollY + $('#exp-footer').outerHeight()
}, 'medium');
}
});
Now I am stuck on how to properly reverse this, ie when the user scrolls back up 365px (the height of #exp-footer), I want #exp-footer to hide() or slideUp() and #sticky-footer-wrap to be displayed once more.
I have tried a few different ways, all of which are buggy - so I think I've been going about this the wrong way. My question is, what would be the best way to achieve this?
fiddle: http://jsfiddle.net/zqPVP/
Related
Here's a full codepen of the situation I will describe in detail below: https://codepen.io/Adam0410/full/MGXjaz/
The javascript contained in the codepen (the core of the issue) is below:
var collapsed = false;
$(window).scroll(function(){
var scroll = window.pageYOffset || document.documentElement.scrollTop;
if (scroll > 207 && !collapsed) {
$("#header").css({
position: "fixed",
height: "50px",
"line-height": "50px"
});
$("#content").css("margin-top", "207px");
$(document).scrollTop(scroll - 50);
collapsed = true;
} else if (scroll < 155 && collapsed) {
$("#header").css({
position: "static",
height: "257px",
"line-height": "257px"
});
$("#content").css("margin-top", "0");
$(document).scrollTop(scroll + 50);
collapsed = false;
}
});
I am attempting to make a large header that is part of the flow of the document, that then turns into a smaller fixed header as you scroll down past it. I want the action of the user scrolling to be smooth during this process.
If you view the pen on mobile (or use chrome's device toolbar) with smooth scrolling and scroll slowly around the breakpoint where the header changes you can see it's completely smooth.
However if you view it on a desktop (with chrome again, or any other browser) the scrolling with a scroll wheel is done in 100-pixel increments. For this reason once again if you scroll around the breakpoint where the header changes you can see it is not smooth.
This occurs since the 100-pixel scrolling doesn't occur instantly and in the process of changing the scrollTop of the document the 100-pixel scrolling animation gets canceled. Is there any way to detect and resume this scrolling animation once I've set the scrollTop property?
Please check https://codepen.io/anon/pen/PeabEL
Changed the js to
$(window).scroll(function(){
var scroll = window.pageYOffset || document.documentElement.scrollTop;
var newHeight = 50;
if(257-scroll>50)
newHeight = 257-scroll;
$("#header").css({
position: "fixed",
height: newHeight+"px",
"line-height": newHeight+"px",
});
});
also added
#content {
...
margin-top:257px;
}
and,
#header {
...
position: fixed;
}
I have another approach with the help of a very small plugin called smoothwheel (Get it here). I extended the answer of #Rohith Murali and created an example. Have a look here:
https://codepen.io/anon/pen/NMBdpx
The plugin itself enables you to scroll smoothly with low impact on performance. Does this fit your needs?
I can't handle such a mind-breaker:
It's common approach to hide page scroll when a tall popup shows. But when you set overflow: hidden to html and body elements, the content automatically returns to it's top (scrollTop: 0). It's no problem to keep scrollTop position, and reset it on popup's disappearing. But if you use transparent mask, user will see unnecessary jump from current scroll position to the top. How to escape this?
In the current Chrome and Firefox, I can set overflow: hidden only to html element to reach what I want, but it's not working on mobile devices.
Maybe someone can propose a good cross-browser solution.
I don't think this should be happening. I would look at the popup code to see if it's the culprit sending the page to the top and using subpar css to position the popup element.
In any case, here's code that ought to counter the behavior you're encountering. Since I cannot reproduce the problem, I cannot test my proposed fix. I think you'll find though that your pop up will be scrolled away out of view.
function keepScroll(){
var x = $('body').scrollLeft() + $(document.documentElement).scrollLeft();
var y = $('body').scrollTop() + $(document.documentElement).scrollTop();
$('html').css({
'overflow':'hidden'
});
$('body').css({
'overflow':'hidden'
});
$(window).scrollTop(y).scrollLeft(x);
}
The sicky footer layout has html and body height equal to '100%'. And when you set overflow:hidden it crops all the content and returns it to the top position.
To avoid this, you should set html and body height to 'auto' if scroll exists (you should check it to keep sticky footer behavior)
function keepScroll(){
var scrollHeight = $('body')[0].scrollHeight > $('html')[0].scrollHeight ? $('body')[0].scrollHeight : $('html')[0].scrollHeight,
keepCSS = scrollHeight > $(window).height() ? {'overflow':'hidden','height':'auto'} : {'overflow':'hidden'};
$('html, body').css(keepCSS);
}
See the fiddle, for live demo
Edit 1
This solution is still not working on mobile (overflow: hidden doesn't disable scrolling on iPad, the position 'fixed' fix for body throw the content to the top), so the issue is open
Edit 2
Find a fix, for mobiles. Maybe it isn't so clean, but works.
var scrollKeeper = (function() {
var scrollHeight = $('body')[0].scrollHeight > $('html')[0].scrollHeight ? $('body')[0].scrollHeight : $('html')[0].scrollHeight,
keepCSS = scrollHeight > $(window).height() ? {'overflow':'hidden','height':'auto'} : {'overflow':'hidden'},
scrollTop = 0;
return {
keep : function() {
scrollTop = $(window).scrollTop();
$('body').css({'position': 'fixed', 'width':'100%', 'top': -scrollTop + 'px'});
$('html, body').css(keepCSS);
},
release : function() {
$('html, body').removeAttr('style').scrollTop(scrollTop);
}
}
})();
Tip: Of course in the real development you should use css classes to avoid removeAttr(style) etc.
Tested on iPhone and Ipad (iOS 8+).
The fiddle http://jsfiddle.net/m1eav032/5/
On my page, I have a div element containing copyright information.
I would like to
detect if the user has scrolled all the way to the bottom of the page.
if so, have the div slide down.
It would also be nice if there was a way that JQuery could tell if I am near the box without having to scroll over it to display the copy right as well.
Thanks, DoubleDogg6
It's simple to detect this.
take a look at this jfiddle:
Detect scrolling to the bottom
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() == $(document).height()) {
alert("bottom!");
}
});
2.
For sliding down a div read the documentation for .slideDown()
jQuery .slideDown()
If you want jQuery, then this should suffice
$(window).scroll(function(){
if ($(window).scrollTop()+$(window).height() == $(document).height()){
// and now, slideDown
$("#your-div-id").animate({
height: /* whatever your final height should be */
}, 200);
} else if ($(window).scrollTop()+$(window).height() < $(document).height() + 50) {
$("#your-div-id").animate({
height: /* whatever your original height was */
}, 200);
}
});
Of course, you combine the animate function with others to maybe fade in the text or something, and change the speed at which the animation happens, currently 200ms.
You also want your div's overflow-y set to hidden,
#your-div-id {
overflow-y: hidden;
}
Check out this JSFiddle demo.
I'm looking for a way to prevent the elastic scrolling that occurs on OS X in both Chrome and Safari.
If you don't understand what I mean, it's when you scroll up while the page is at the top, or down when the page is at the bottom, and it shows a gray background behind the page.
There is a css solution for single page apps where you just add overflow:hidden to the html or body
However, I need to be able to scroll.
I've come up with a solution using Javascript (JQuery), but it's only for scrolling passed the top, and only works for chrome. Also, it's a bit buggy in Safari.
$(window).on('scroll', function(e){
scrollAmount = $(this).scrollTop();
if(scrollAmount < 1){
$(this).scrollTop(1);
}
});
So that's just checking of the user scrolls below 1 meaning they try to scroll up passed where the page ends. I tried 0 but that didn't work.
I haven't been able to find a way to check if the user scrolls passed the bottom of the page.
So any thoughts?
Edit:
$(window).on('scroll', function(e){
scrollAmount = $(this).scrollTop();
if(scrollAmount < 1){
$(this).scrollTop(1);
}
if(scrollAmount > $(document).height() - $(window).height()){
$(this).scrollTop($(window).height());
}
});
Now I've added a check for if we scroll passed the bottom of the page. This method is not working though, it's bouncing around very ungracefully.
When you quickly scroll up to the top, the elastic browser causes the scroll top to become negative. Using the st <= 0, will make sure no action is taken when this happens.
$(window).on('scroll',function(){
var dh = $(document).height(),
wh = $(window).height(),
st = $(window).scrollTop();
if (st <= 0) {
$(this).scrollTop(0);
} else if (st + wh >= dh) {
$(this).scrollTop(dh);
}
});
You can now use overscroll-behavior:
html, body {
overscroll-behavior: none;
}
While I dislike the methodology, you can use jQuery to get the document height (and thus the bottom of the page for the scroll distance using $(document).height();)
Another method would be to wrap the entire page with a <div id="preventScroll"></div> wrapper, with the property overflow: scroll; height: 100%; width: 100%;
That would be a separate scrolling device and prevent your whole issue.
I am hoping someone can kindly help. I'm by no means a programmer, and I'm trying to learn how to create a slightly different sticky div than normal. This is what I want to achieve:
when the div #projectwrapper scrolls up the screen, and is 150px from the top of the window, it should stick and stay there while the rest of the page scrolls
when scrolling back down the page, the div should return to its normal place in the page when that comes into view.
I have been trying the demos and examples, and I can nearly get it working. But it will only get activated when it goes to the very top of the window, and it stick at the very top. However I need the activation and sticking to happen 150px from the top.
This is what I have so far.
$(document).ready(function() {
$('#projectwrapper').waypoint(function(event, direction) {
}, {
offset: 150
}).find('#projectdescription').waypoint(function(event, direction){
$(this).parent().toggleClass('sticky', direction === "down");
event.stopPropagation();
});
});
I haven't used waypoint. You can do using some simple jQuery:
var projectWrapperPosition = $('#projectwrapper').position().top; //div position
$(window).scroll(function() { //when window scrolls
if($(window).scrollTop() > (projectWrapperPosition - 150)) //check if position of the window is 150px or smaller than the position of specified div has
$('#projectwrapper').addClass('change-position'); //.change-position position fixed the div
else
$('#projectwrapper').removeClass('change-position');
});
css:
.change-position {
top:150px;
position:fixed;
width:100%;
background:red;
}
Check demo: http://jsbin.com/uxizab/2/ (scroll to see the effect)