Position fixed, but scroll on <body> - javascript

I have this situation:
my website, which I am creating, has a left sidebar, which must be set to height 100%, while scrolling the webpage, and the content inside it is definitely over 1000px height.
because of the height of the content, I get vertical scroll on this sidebar element, and when my content has enough content, I get another scroll for this section.
What I have to do is to, somehow, transfer, scroll from the "fixed" element to the main page scroll...
I hope that you can understand me...
I hope that this screenshot, can also help you to understand what I ask:
link
Thank you in advance for you answers.

Your question got me interested, so I gave it a try.
You could have your sidebar set up like so:
#sidebar{
position:fixed;
min-height:100%;
top:0;
left:0;
/* ... */
}
Now, to make it scroll, we can play with its margin-top css property:
If we scroll down, we decrement it unless we scrolled past its
height.
If we scroll up, we increment it unless it's above zero.
I created a ScrollingSidebar class with 2 functions in order to deal with that:
// ScrollingSidebar class
// Define some variables and bind events
function ScrollingSidebar(el){
this.sidebar = el;
var that = this;
that.updateVariables();
document.addEventListener('scroll',function(){that.scrollSidebar();});
window.addEventListener('resize',function(){that.updateVariables();});
}
// Updates variables used for calculation
ScrollingSidebar.prototype.updateVariables = function(){
this.height = parseInt( getComputedStyle(this.sidebar).height );
document.body.style.minHeight = this.height + 'px';
this.winHeight = parseInt( window.innerHeight );
this.previousScrollPos = Math.floor( document.body.scrollTop ||
document.documentElement.scrollTop ||
document.body.parentNode.scrollTop
);
this.scrollSidebar();
};
// Updates the sidebar's margin-top
ScrollingSidebar.prototype.scrollSidebar = function(){
var curScrollPos = Math.floor( document.body.scrollTop ||
document.documentElement.scrollTop ||
document.body.parentNode.scrollTop
);
if(this.previousScrollPos < curScrollPos){
this.sidebar.style.marginTop = - Math.min(-parseInt( getComputedStyle(this.sidebar).marginTop ) + (curScrollPos - this.previousScrollPos),
this.height-this.winHeight) + 'px';
} else {
this.sidebar.style.marginTop = Math.min(0,parseInt( getComputedStyle(this.sidebar).marginTop ) + this.previousScrollPos-curScrollPos) + 'px';
}
this.previousScrollPos = curScrollPos;
};
You can use it like so:
// Create an instance of ScrollingSidebar
var sidebar = document.getElementById('sidebar');
var x = new ScrollingSidebar(sidebar);
JS Fiddle Demo (with a small amount of content)
JS Fiddle Demo (with a lot of content)
Note: I did not take the time to comment my code very well, but if you have any question about it or any problem with it, feel free to ask.
If your website is responsive and you don't want this method to be used on small screens, you might want to consider using a condition to disable it.

Related

Stop element from being fixed once scrolled past value

I have a fixed .widget element that remains visible at all times. Currently however, it scrolls over the footer area. My goal is to stop the widget before it hits the footer.
CSS
.widget {
position:fixed;
height:450px;
width:300px;
}
footer {
height:450px;
width:100%;
}
My route I'm taking is currently:
jQuery
var $bodyheight = $('body').height();
var $footerheight = $('footer').height();
var $widgetheight = $('.game_widget').height();
var $pageheight = $bodyheight - $footerheight - $widgetheight;
$(window).on('scroll', function() {
console.log($(this).scrollTop())
});
My next step would be to loop through to see if scrollTop > $pageheight then update some CSS.
Is this the best way of going about this? Is there a cleaner/simpler way to achieve the same result?
I have managed to solve this quite simply. Inside the scroll function I set 2 variables, one for the position of the fixed element, the other for the position of the footer. These return the exact value from how far the top of the element is from the top of the page. For the fixed element I need to know the distance to the bottom of this element so I also include the height.
var $fixedpos = $(".game_widget").offset().top + $('.game_widget').height();
var $footerpos = $("footer").offset().top - 25; // 25 accounts for margin
Using a simple if/else the CSS is updated to display none/initial depending on whether $fixedpos > $footerpos (i.e. the fixed element is overlapping the footer).
if ($fixedpos > $footerpos) {
$('.game_widget').css('display','none');
} else {
$('.game_widget').css('display','initial');
}
This works, however there is a 'flicking' effect as the fixed element overlaps the footer. This is due to the function executing extremely rapidly. The solution to the flicker is to use this simple 'throttling' plugin that adds a short delay (of your choice) between each execution of a function - http://benalman.com/projects/jquery-throttle-debounce-plugin/
You then just need to bind the on scroll function to the throttle:
function scrolling() {
console.log($(".game_widget").offset().top + $('.game_widget').height());
console.log($("footer").offset().top - 25);
var $fixedpos = $(".game_widget").offset().top + $('.game_widget').height();
var $footerpos = $("footer").offset().top - 25;
if ($fixedpos > $footerpos) {
$('.game_widget').css('display', 'none');
} else {
$('.game_widget').css('display', 'initial');
}
};
$(window).on('scroll', $.throttle(250, scrolling)); // 250ms between executing the function
});
This 250ms delay stops the function from executing so rapidly that the flickering effect occurs.
Hope this helps others trying to solve this problem.

Jquery change position fixed to static based on viewport between two div

Im new to jquery.
I want to create a fixed bottom banner, and when i scroll down.. that banner will stop at the end of selected div that i want (in this case between "container-content-top" and "container-content-bottom" with smooth transition (not jumping like i did).
i already create using jquery,
<script>
$(document).ready(function(){
var topOfrel = $("#banner1").offset().top;
var topOffooter = $("#container-content-bottom").offset().top - $("#banner1").height() - $("#header-nav").height() - 120;
$(window).scroll(function(){
var y = $(window).scrollTop();
if (topOffooter > y) {
jQuery("#banner1").css("position", "fixed");
} else {
jQuery("#banner1").css("position", "static");
}
});
})
</script>
But it seems the banner will move into the position that i want (between 2 div) after certain px scroll. I already working on this for 3 days :(.
I want the banner will not fixed and change to static to the position i want with smooth transition after i scroll and responsive too.
here's my full code : http://jsbin.com/IDonagi/1/edit?html,css,output
anyone have better solution ?
Thx before guys :)
You want to trigger the switch when bottom border of browser window crosses the top position of #container-content-bottom. The correct code to determine them would be:
// topOffooter is the top offset of content after the banner.
// Have to add banner height here because its initial position is fixed,
// and therefore not counted when determining position of #container-content-bottom.
var topOffooter = $("#container-content-bottom").offset().top + $("#banner1").outerHeight();
...
// y is top offset of current bottom border of browser window
var y = $(window).scrollTop() + $(window).height();
Thanks for Leo,This is my solution for this problem,
<script>
$(document).ready(function() {
var topOfrel = $("#banner1").offset().top;
var topOffooter = $("#container-content-bottom").offset().top + $("#banner1").outerHeight();
$(window).scroll(function() {
var y = $(window).scrollTop() + $(window).height();
if (topOffooter > y) {
jQuery("#banner1").css("position", "fixed");
} else {
jQuery("#banner1").css("position", "static");
}
});
})
</script>
and for mobile device ready i simply adda this to head :
<meta name="viewport" content="user-scalable=no, width=device-width,initial-scale = 1.0,maximum-scale = 1.0" />
hope this help someone if needed :)

How to Smoothly Prevent a Fixed Element from Scrolling Past A Specified Element

Essentially what I want to do is keep my blog posts' meta information on the screen at all times. As it is, the meta info (title, author, etc.) is displayed to the left of the post content, and I have it set up where the meta information stays on screen smoothly when I scroll down. However, I'm having an issue:
I can't get it to smoothly not scroll over the #comments DIV. It either overlaps or is jumpy, depending on how I tweak the code.
Here is the JS function I'm using:
function brazenlyScroll() {
var element = jQuery(".single-post .headline_area");
var top = element.offset().top - 50;
var elementHeight = 26 + element.height();
var maxTop = jQuery("#comments").offset().top - elementHeight;
var scrollHandler = function() {
if (jQuery(document).width() > 1035) {
var scrollTop = jQuery(window).scrollTop();
if (scrollTop<top) {
element.css({position:"relative",top:""})
} else if (scrollTop>maxTop) {
element.css({position:"absolute",top:(maxTop+"px")})
} else {
element.css({position:"fixed",top:"50px"})
}
}
}
jQuery(window).scroll(scrollHandler);
jQuery(window).resize(scrollHandler);
scrollHandler();
}
That code is included via an external JS file and is called at the bottom of the page. You can see all of this in action here: http://www.rickbeckman.org/dumber-and-dumber-and-dumber/
Any help would be greatly appreciated.
You can make the comments div shrink to right by giving it a 300px padding when meta block reaches maxTop.
I just tested ur code and was able to fix the overlapping by changing 26 to a bigger number, say about 60.
var elementHeight = 26 + element.height();
Hope this helps.

Change margin-top as user scrolls

I am trying to get a div to scroll up at the same amount of pixels as the user scrolls down the page. For example, in Google Chrome when using the mouse wheel, it scrolls down in about 20px intervals. But when you scroll down using the handle, the scrolling amount varies.
Here is my code so far:
var scrollCtr = 50;
$(window).scroll(function(){
scrollCtr = scrollCtr - 20;
$('div.nexus-files').css('margin-top', scrollCtr + 'px');
});
There are a few problems with this:
The user scrolling varies
It needs to subtract from margin-top if scrolling down and add to margin-top if scrolling up
Here is an example:
http://www.enflick.com/
Thanks for the help
You're doing it the wrong way, what you are trying to do should be done using position: fixed on div.nexus-files
div.nexus-files{position: fixed; top: 0;}
but anyway - if you still want to know what you can do with the scroll event - you better get to scrollTop of the document and set the margin-top to the same value
window.onscroll = function(event){
var doc = document.documentElement, body = document.body;
var top = (doc && doc.scrollTop || body && body.scrollTop || 0);
document.getElementById('nexus-files_id').style.marginTop = top+'px';
}
I'm using pure Javascript instead of jQuery because of the overhead that might be crucial when the browser need to calculate stuff in a very short amount of time (during the scrolling). [this can be done even more efficient by storing reference to the element and the doc... but you know..)
I used id based selector to get the specific element instead of class based
AND I SAY AGAIN - this is not how you should do what you were trying to do
Why not using the actual scroll offset as reference or position ?
// or whatever offset you need
var scrollOffset = document.body.scrollTop + 20;
// jQuery
var scrollOffset = $("body").scrollTop() + 20;
Finally Got it
Here is the code I used to accomplish the task.
Most of the code is from http://enflick.com and I modified it to work with my individual situation.
jQuery(window).load(function(){
initParallax();
});
// parallax init
function initParallax(){
var win = jQuery(window);
var wrapper = jQuery('#wrapper');
var bg1 = wrapper.find('.nexus-files');
var koeff = 0.55;
if (bg1.length) {
function refreshPosition(){
var scrolled = win.scrollTop();
var maxOffsetY1 = 450;
var offsetY1 = scrolled * koeff;
var offsetY2 = scrolled * koeff - (maxOffsetY1 * koeff - offsetY1);
if (offsetY1 <= maxOffsetY1 * koeff - offsetY1) {
bg1.css("margin-top", +-offsetY1+"px");
//alert(+-offsetY1+"px");
}
}
refreshPosition();
win.bind('resize scroll', refreshPosition);
}
}

Adjust top position according to height of div with javascript

function jsiBoxAdjustTop()
{
var top
if ( jsiBox.preloadImg.height <= 699){
top = 216;
}
else{
top = 17;
}
jsiBox.boxNode.style.top = (top) + 'px';
}
I'm using that function to adjust a div's top position depending on the image that is in it's height. It's on a light box sort of script so every time I click the next button, a new image which could either be taller or smaller appears. It's working alright and it adjusts its position when the image is taller but my problem is it just jumps to that position. I'm really new to javascript so can anyone help me out to make this as if it's travelling/animating to it's position? I tried using setTimeOut but I think I was doing it wrong. I'd really love to know what I'm doing wrong.
Here's the full script if that helps. Link
you can use jQuery or YUI to do animate, such as
jQuery(jsiBox.boxNode).animate({'top': top}, 3000);
or you can write some simple code with setTimeout just for this case;
following code assume the begin top is 0.
var boxStyle = jsiBox.boxNode.style;
function animateTop(to) {
boxStyle.top = parseInt(boxStyle.top, 10) + 1 + 'px';
if (parseInt(boxStyle.top, 10) != to) {
setTimeout(function() {
animate(to);
}, 50);
}
}
animateTop(top);

Categories