fixed when scrolling but stop at footer - javascript

UPDATE
I've been testing a bit with the sticky position but it doesn't work on Safari version 11.1. Safari is the highest browser in analytics. So I guess I'm still looking for a jQuery solution. Although the answer from MichaƂ Sadowski helped allot.
I'm trying to get a fixed element when scrolling but it needs to stop being fixed and start scrolling when it reaches the footer.
I'm using this code: Make scrolling sidebar stop at footer
My CSS, HTML are exactly the same as in this fiddle right now.
But the problem is, my fixed element needs to have an offset of +60 because my header (menu) is 55px in height. I've got the offset to work sort off.
Right now, I use the following code.
function sticky_relocate() {
var window_top = $(window).scrollTop()+60;
var footer_top = $("#footer").offset().top;
var div_top = $('#sticky-anchor').offset().top;
var div_height = $("#sticky").height();
var padding = 20; // tweak here or get from margins etc
if (window_top + div_height > footer_top - padding)
$('#sticky').css({top: (window_top + div_height - footer_top + padding) * -1})
else if (window_top > div_top) {
$('#sticky').addClass('stick');
$('#sticky').css({top: 60})
} else {
$('#sticky').removeClass('stick');
}
}
$(function () {
$(window).scroll(sticky_relocate);
sticky_relocate();
});
This kind of works. But when I reach the #footer the top jumps from 60px to -1.8414. So the transition isn't seamless. It "jumps" when I reach the footer.
I've tried a whole bunch of things.
Like adding 60px to the #sticky div.
When It removes the class stick I followed that up with $('#sticky').css({top: 60})
But nothing takes away the "jump" is there anyone who could help me to get this to work or has a similar code snippet?. Thanks in advance!

Okay, it depends a lot on your html structure. But let's say you have it like that:
<div class="container">
<div class="content">
<div class="sticky">
</div>
</div>
<div class="footer">
</div>
</div>
Now, in css:
.content{
position: relative
}
.sticky{
position: sticky;
top: 60px;
}
It should do exactly what you need.

Related

Dynamically change height of div using onscroll not working

I am trying to use jquery to change the height of a div across a bottom and top nav as on this codepen.
The jquery is this:
$(document).ready(function() {
var lastScrollTop = 0;
var img = 100;
$(window).scroll(function() {
var st = $(this).scrollTop();
if (st > lastScrollTop) {
// downscroll code
console.log('downward')
img = img + 1;
$('.img').height(img);
} else if (st < lastScrollTop) {
// upscroll code
console.log('upward')
img = img - 1;
$('.img').height(img);
}
lastScrollTop = st;
}).scroll();
})
body {
height: 2000px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Below is the html for the jquery:
<div class='wrapper'>
<nav>
<div class='topnav'>
<div class='img'>
</div>
</div>
<div class='bottomnav'>
</div>
</nav>
<div class='main'>
I am main content
</div>
</div>
The problem is that the console.logs scrolling down doesn't match the console.logs scrolling upwards. So the polygon div spanning both navs doesn't end up where it's supposed to. Please see the image below for console.logs:
I am trying to make the top nav disappear as you scroll the grey nav becomes fixed and the polygon shaped div becomes the size of the grey nav component. The idea is to get a similar effect like the one on fantasy premier leagues website.
Any help would be appreciated. If you need more details please ask and ill provide clarification.
Scrolling upwards and downwards do not always happen in increments of 1, hence the mismatch. If you scroll upwards slowly, its count would exceed downwards scroll. Instead what you need to do is, determine the breakpoints where you want the changes to happen. So for e.g. you want the top navbar to disappear on scroll. The top navbar has height of 50, so when your scrollTop exceeds 50, make grey bar position fixed and at the top. Check this codepen https://codepen.io/anon/pen/RxjoeG
$(document).ready(function () {
var lastScrollTop = 0;
var img = 100;
$(window).scroll(function () {
var st = $(this).scrollTop();
if(st >= 50) {
$('.bottomnav').css({'position':'fixed', 'top':0});
} else {
$('.bottomnav').css({'position':'initial'});
}
}).scroll();
})

Change z-index of div 2 once div 1 becomes sticky

On this page http://www.younity.co.nz/testScrolling.html I need to change the z-index of the second navigation menu that appears from behind the video container so that it has a higher z-index and blocks out the grey 'Y' graphic once the initial menu has scrolled off the page. Hope that makes sense. So I need to test that the initial nav menu has started to leave the top of browser or it has left.
This is housing menu 1
<div class="nav-wrap-height">
<div class="nav-wrap-box">
menu
</div>
</div>
When it scrolls to the top '.nav-wrap-height' becomes sticky
.nav-wrap-height{
float:left;
width:100%;
position:relative;
z-index: 100;
position: sticky;
top: 0;
}
What I want to do is change the z-index of the second menu (.nav-wrap-box#showNow) once .nav-wrap-height has become sticky
<div class="cntrl-nav-2" id="showNow">
<div class="nav-wrap-box">
menu
</div>
</div>
.cntrl-nav-2{z-index:10;}
I'm trying the below but not getting any result.
<script>
var distance = $('.nav-wrap-height').offset().top,
$window = $(window);
$window.scroll(function() {
if ( $window.scrollTop() >= distance ) {
$('.cntrl-nav-2').css({
z-index:'300'
});
}
});
</script>
Any assistance with this problem would be really most helpful.
Cheers
Grant
You are using the wrong selector
$('.nav-wrap-box.showNow')
when it should be
$('.nav-wrap-box#showNow')
This is what I was after. I was writing the z-index part wrong.
var distance = $('.nav-wrap-height').offset().top,
$window = $(window);
$window.scroll(function() {
if ( $window.scrollTop() >= distance ) {
$('.cntrl-nav-2').css('z-index', 200);
}
else{
$('.cntrl-nav-2').css('z-index', 10);
}
});

How to scroll div with page without position: fixed?

I found this script:
$(function(){
var btn = $('.social');
var btnPosTop = btn.offset().top;
var win = $(window);
win.scroll(function(e){
var scrollTop = win.scrollTop();
if(scrollTop >= btnPosTop){
btn.css({position:'fixed',left:'82%'});
}else if(btn.css('position') === 'fixed'){
btn.css({position:'',left:''});
}
});
});
Which works great. I changed the original field to '.social' so that it would work with my code.
I am not looking for a crap fix of "left: 82%" though.
I want to avoid the position: fixed; and simply scroll the div where it sits.
My tree is #container .contain .single-content .social
The position: fixed is my main problem, but if you know, then stopping .social once it reaches the very bottom of .single-content would be a major plus!!
Hopefully I have provided enough information.
HTML:
<div id='container'>
<div class='contain'>
<div class='single-content'>
<div class='first'>
<div class='social'>
content here.. no p tags.. just facebook, twitter buttons etc.
</div>
</div>
</div>
</div>
</div><!-- container -->
EDIT:
website in question: thelackof.com
You can see how the social icons are offset a bit because of my left:82%
If I remove the left:, then the new position: fixed will jump my div out of the containing div and all the way to the left of the next containing div.
I would like it to stay where it is and scroll down once reached.
EDIT no. 2: First of all:
So it will get a value that won't disturb with the main-contents:
#container .contain .single-content .first .social {
float: left;
position: absolute;
width: 15%;
right: 0;
}
Then this:
$(function(){
var btn = $('.social');
var btnPosTop = btn.offset().top;
var win = $(window);
win.scroll(function(e){
var scrollTop = win.scrollTop();
if(scrollTop >= btnPosTop){
btn.css({position:'fixed'});
}else if(btn.css('position') === 'fixed'){
btn.css({position:''});}
if (btnPosTop >= $('.single-content').offset().top-92){
btn.css({position:''});
}
});
});
I might be getting your question wrong but I think this is what you asked for. I removed the left property.
Hope it helps :)
EDIT: I've added:
if (btnPosTop >= $('.single-content').offset().top){
btn.css({position:''});
}
So it will scroll until the btnPosTop is greater than the offset().top of .single-content
Please let me know if it works

jquery background image scroll effect speed issue

I have purchased a template for my shopify store that scrolls a site wide absolutely positioned background image at a slower speed than what the user scrolls for a neato perspective effect.
I have found the script used in the template that animated the scrolling effect for the background image. It is as follows:
<script type="text/javascript">
(function($) {
if(device.desktop()){
// PARALLAX INIT
$(window).bind('scroll',function(e){
parallaxScroll1();
});
function parallaxScroll1(){
var scrolled = $(window).scrollTop();
$('#wrapper .wrapper_bg').css('top',(0+(scrolled*.75))+'px');
}
// SMOOTHSCROLL 4 WEBKIT
var platform = navigator.platform.toLowerCase();
if (platform.indexOf('win') == 0 || platform.indexOf('linux') == 0) {
if ($.browser.webkit) {
/* jquery.simplr.smoothscroll - https://github.com/simov/simplr-smoothscroll */
;(function(e){"use strict";e.srSmoothscroll=function(t){var n=e.extend({step:85,speed:600,ease:"linear"},t||{});var r=e(window),i=e(document),s=0,o=n.step,u=n.speed,a=r.height(),f=navigator.userAgent.indexOf("AppleWebKit")!==-1?e("body"):e("html"),l=false;e("body").mousewheel(function(e,t){l=true;if(t<0)s=s+a>=i.height()?s:s+=o;else s=s<=0?0:s-=o;f.stop().animate({scrollTop:s},u,n.ease,function(){l=false});return false});r.on("resize",function(e){a=r.height()}).on("scroll",function(e){if(!l)s=r.scrollTop()})}})(jQuery);
/* jquery.mousewheel - https://github.com/jquery/jquery-mousewheel */
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});
$.srSmoothscroll({
step: 55,
speed: 100,
ease: 'swing'
});
}
};
};
})(jQuery);
</script>
The issue that I am having is that the scrolling effect moves to quickly, and by the time the user has reached the bottom of the page they are viewing, the background image has prematurely cut off.
I have been fidling around with the values in this script, trying to slow down the effect, with no success. Any insights?
Thanks! You can view this script in action on our site at:
http://ts8276eb.myshopify.com/
the password is: yandasmusic
That code is way too complicated for me to even consider trying to debug.
So I made a much simpler version.
var wrapper = document.getElementById('wrapper'),
checkbox = document.getElementById('scrolleffect');
function parallax() {
if( checkbox.checked) {
wrapper.style.backgroundPosition = "center " + (this.scrollTop / (this.scrollHeight - window.innerHeight) * 100) + "%";
}
else {
wrapper.style.backgroundPosition = "";
}
}
document.body.onscroll = function() {parallax.call(document.body);};
document.documentElement.onscroll = function() {parallax.call(document.documentElement);};
#wrapper {
background: #333 url('http://cdn.shopify.com/s/files/1/0810/2125/t/21/assets/body_bg_img.png?677044079657970527') no-repeat scroll center top;
color: white;
padding: 8px;
}
.spacer {
height: 800px;
}
body {
margin: 0;
}
<div id="wrapper">
<p>Content!</p>
<p style="position: fixed;"><label><input type="checkbox" id="scrolleffect" /> Toggle background scroll effect</label></p>
<div class="spacer"></div>
<p>More content!</p>
<div class="spacer"></div>
<p>Content ends</p>
</div>
The important part here is that the background position is updated according to how far down the page we've scrolled. It ranges from center 0% to center 100%. The convenient thing about background image positioning is that 0% means "align top of image with top of element", and 100% means "align bottom of image with bottom of element". Values are interpolated in-between, so 25% would be "align the top quarter mark of the image with the top quarter mark of the element".
Much simpler.
The numbers appear to be crunched here:
$('#wrapper .wrapper_bg').css('top',(0+(scrolled*.75))+'px');
So it currently scrolls 25% slower than the page. If you lower this number, it will go more slowly...
$('#wrapper .wrapper_bg').css('top',(0+(scrolled*.25))+'px');

Sticky header after some scrolling?

okay here's an example of what i am trying to ask,
the nav bar of usatoday.
I'm using bootstrap affix. here's my code
<div class="header">
<div class="header-1">
<h1>this is some logo</h1>
</div>
<div class="header-2">
<h3>this is some heading</h3>
</div>
</div>
<div class="content" style="height:2500px;">
</div>
<div class="footer">
this is a footer
</div>
JavaScript
$('.header-2').affix({
});
how can I make the div header-2 to be fixed on the top, (when there is some scrolling and the div header-2 just reach the top position) as of the site I've mentioned earlier?
I would love to see the header-1 and header-2, but some scrolling should hide header-1 and stick header-2 to the top most.
thanks
See this Jsfiddle
you can check the position of the slider and add class accordingly
$(window).scroll(function () {
if( $(window).scrollTop() > $('#header-2').offset().top && !($('#header-2').hasClass('posi'))){
$('#header-2').addClass('posi');
} else if ($(window).scrollTop() == 0){
$('#header-2').removeClass('posi');
}
});
use jquery look at this example
http://jsfiddle.net/5n5MA/2/
var fixmeTop = $('.fixme').offset().top; // Get initial position
$(window).scroll(function() { // Assign scroll event listener
var currentScroll = $(window).scrollTop(); // Get current position
if (currentScroll >= fixmeTop) { // Make it fixed if you've scrolled to it
$('.fixme').css({
position: 'fixed',
top: '0',
left: '0'
});
} else { // Make it static if you scroll above
$('.fixme').css({
position: 'static'
});
}
});
Bootstrapped answer using Bootstrap.affix()
$('.header-2').affix({
offset: {
top: function () {
return (this.top = $(".header-2").offset().top);
}
}
});
This also needs CSS for the fixed positioning (see the Docs).
The affix plugin toggles between three classes, each representing a
particular state: .affix, .affix-top, and .affix-bottom. You must
provide the styles for these classes yourself (independent of this
plugin) to handle the actual positions.
.header-2.affix {
top: 0;
}
Working example at Bootply: http://www.bootply.com/S03RlcT0z0
<style>
.header {
top: 0%;
left: 0%;
width: 100%;
position:fixed;
}
</style>
I'm sorry didnt look at your problem carefully.
This may helps you Issue with Fixed Header and Bootstrap Affix / Scrollspy - Not jumping to correct location

Categories