I have fixed div on bottom of my page that works well. I wonder if there is some simple way to make it "stop" on some place in page when user srolls down to it. I want it to remain fixed on bottom, until user scrolls down to some defined place on page and than stick it to the page and scroll like the rest of content. Any suggestions?
I tried setting something up on jsfiddle. While I was writing it up, I see that others have posted their alternatives. In case mine helps in any way: http://jsfiddle.net/PnUmM/1/
I set the position to relative in the CSS, calculate where it is on document load to keep the info aside and then set it to fixed.
var sticky_offset;
$(document).ready(function() {
var original_position_offset = $('#sticky_for_a_while').offset();
sticky_offset = original_position_offset.top;
$('#sticky_for_a_while').css('position', 'fixed');
});
$(window).scroll(function () {
var sticky_height = $('#sticky_for_a_while').outerHeight();
var where_scroll = $(window).scrollTop();
var window_height = $(window).height();
if((where_scroll + window_height) > sticky_offset) {
$('#sticky_for_a_while').css('position', 'relative');
}
if((where_scroll + window_height) < (sticky_offset + sticky_height)) {
$('#sticky_for_a_while').css('position', 'fixed');
}
});
I made this up for you: http://jsfiddle.net/XCYFG/1/.
$(document).ready(function() {
window._div1 = $('#div1'); //selector is expensive
window._window = $(window);
$(window).scroll(function(e) {
_div1.css("top",
Math.min(_window.height(),
window.scrollY + 100)
+ _window.height() - _div1.height() - 110);
}).scroll();
});
I have a plugin that does the opposite - it's in the flow of the webpage, and when the user scrolls past it, it gets fixed to the viewport. What it actually does though is apply a css class to the element, so you should be able to use it as is.
You can find the plugin here:
https://github.com/hanssonlarsson/jquery-fixedscroll
Then I would suggest you have your element in the flow of your webpage:
<div id="sometimesFixed">content</div>
With css:
#sometimesFixed {
position: fixed;
bottom: 0;
}
#sometimesFixed.scroll {
position: static;
}
And apply the plugin like so, in your JavaScript:
$('#sometimesFixed').fixedscroll({className: 'scroll'});
There is also a more general plugin, very new, called jquery-waypoints. The idea is to bind any code to "waypoints", points on the webpage where, when the user scrolls past them, some code is executed.
https://github.com/imakewebthings/jquery-waypoints
It's probably more optimized and a better fit than my plugin, but YMMV!
Related
I am trying to get the height of my navigation and apply it to a margin-top so I can offset my banner. My navigation is fixed so I'm trying to compensate for that so my banner isn't hidden underneath.
// Offset Banner to Height of Navigation
function bannerOffset() {
var bannerTop = $('.x-navbar').height();
$('#banner-carousel').css('margin-top', bannerTop);
}
This, I thought would do it, but it doesn't reflect anything at all in the front-end.
UPDATE
$(document).ready(function() {
var bannerTop = $('.x-navbar').outerHeight();
$('.x-main').css('margin-top', bannerTop);
$(window).scroll(function() {
var bannerTopScroll = $('.x-navbar.scroll').outerHeight();
if ($(document).scrollTop() > 1) {
$('.x-main').css('margin-top', bannerTopScroll);
}
});
});
So I thought I had this, but on load, the margin-top of .x-main is 245px. When I scroll it becomes 85px. I can see the numbers go down to that. The issue is when I scroll back up to the top the value doesn't go back to 245px. It's not very consistent, but I often get 144px. I should add that, and this is probably why, I have another function that changes the height of my .x-navbar when .scroll is added to it.
$(window).scroll(function() {
if ($(document).scrollTop() > 1) {
$('.x-navbar').addClass('scroll');
} else {
$('.x-navbar').removeClass('scroll');
}
});
So I am not sure how to make this all smooth and working properly. If I reload the page the .x-mainis back to 245px. When I scroll back to the top it's not calculating properly.
Your code works. Maybe you want to use $.outerHeight() instead, your selectors are wrong, or you're experiencing margin collapsing.
It's worth noting that $.height() returns an integer value, so in your $.css() line, you should change bannerTop to bannerTop + 'px' so that the CSS has a unit and not just a number... but it looks like jQuery is doing that automagically for me here. You might try it and see.
var bannerTop = $('.x-navbar').height();
$('#banner-carousel').css('margin-top', bannerTop);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="x-navbar">x-navbar<br>x-navbar<br>x-navbar<br>x-navbar<br>x-navbar<br>x-navbar<br>x-navbar<br>x-navbar<br></div>
<div id="banner-carousel">banner carousel</div>
I have a form that is sticky on every page, and I need it to stop being sticky when it reaches the top of the footer. I have this working properly, but I need it to become sticky again when scrolling back up the page. Anything glaringly wrong?
$(window).scroll(function(){
var footerTopPos = $('#footer-wrapper').offset().top;
var navBottomPos = $('#footer-form-wrapper').offset().top;
if(navBottomPos >= footerTopPos) {
$('#footer-form-wrapper').addClass('sticky');
} else {
$('#footer-form-wrapper').removeClass('sticky');
}
});
To clarify, the first part works perfectly. The css changes from "fixed" to "absolute" and the form stays in place. The problem is, I want it to revert back to "fixed" when you start scrolling back up the page (my else statement). This part does nothing at all.
Here is a rough jsfiddle to show the issue http://jsfiddle.net/L693f5bg/14/
--Edit--
To keep what you have started with the same and not use any other plugins you have to make sure you are declaring the variable outside the scroll function so that it doesn't get changed every time you scroll and change its position.
$(function () {
var footerTopPos = $('#footer-form-wrapper').offset().top;
$(window).scroll(function () {
var windowTopPos = $(window).scrollTop();
if (windowTopPos >= footerTopPos) {
$('#footer-form-wrapper').css('position', 'absolute');
$('#footer-form-wrapper').css('top', '0');
} else {
$('#footer-form-wrapper').css('position', 'fixed');
$('#footer-form-wrapper').css('bottom', '0');
$('#footer-form-wrapper').css('top', 'auto');
}
});
});
Updated your JSFiddle
Personally I recommend using Waypoints.js and the sticky elements plugin. It does everything and it's super clean and easy to implement. include the jquery.waypoints.js and the sticky plugin then initialize using:
var sticky = new Waypoint.Sticky({
element: $('#footer-wrapper')[0],
offset: '90%',
stuckClass: 'unstuck'
});
I updated the JSFiddle using the Waypoints.js plugin
Problem:
I'm trying to fadeIn and fadeOut div class="audioBox" once the user scrolls past the header. What I have seems to work fine, except for when the page is loaded and I'm already past the 835px height of the header/
Q: What I'm seeing is when I scroll the audioBox quickly fades in and then fades out, despite scroll >= header How do I prevent this from happening?
scripts.js
// If the reader scrolls past header, show audioBox
var scroll = $(window).scrollTop();
var header = $("header").height();
if (scroll >= header) {
$(".audioBox").fadeIn();
} else if (scroll <= header) {
$(".audioBox").fadeOut();
}
I tried implementing what you're describing in jsfiddle at http://jsfiddle.net/3wqfp2ch/1/.
I'd approach it a bit differently, based on the following ideas:
I personally prefer letting CSS take care of visual stuff via classes, and let jQuery take the simple responsibility of controlling when the classes should be added/removed. I think it makes for a better relationship between the two systems and allows each to do their thing better & more neatly.
I didn't see where you were listening for scroll events on the window, which is essential for figuring out whether a user's scroll position is before or after the header, so have included this in my code
I don't think we need multiple if conditions - there's just one question: "Is the scroll position greater than the header height?".
Here's the JS:
var headerHeight = $("header").height();
var audioBox = $('#audioBox');
$(window).on('scroll', function(){
var scrollPosition = $(window).scrollTop();
if (scrollPosition > headerHeight) {
audioBox.addClass('is-visible');
} else {
audioBox.removeClass('is-visible');
}
});
Check out my fiddle at http://jsfiddle.net/3wqfp2ch/1/ for the HTML & CSS that this relates to, and the working demo putting it all together.
I can't test whether this suffers from the same issue regarding you loading at a point already past the header height from jsfiddle unfortunately, but I wouldn't be expecting the behaviour you described using the code above.
Let me know how you get on!
Calling .fadeIn() or .fadeOut() all the time and having an overlap in the conditions might be the problem.
Try this:
// If the reader scrolls past header, show audioBox
var scroll = $(window).scrollTop();
var header = $("header").offset().top + $("header").height(); // should include the header's offset as well
if (scroll >= header) {
$(".audioBox:hidden").fadeIn();
} else if (scroll < header) {
$(".audioBox:visible").fadeOut();
}
I was wondering how sites like Facebook, with their timeline feature, float a certain element (usually a menu bar, or sometimes a social plugin, etc) when the user has scrolled past a point such that the top of the element is off the screen, etc.
This could be seen as a more general JavaScript (jQuery?) event firing when the user has scrolled to a certain element, or scrolled down a certain number of pixels.
Obviously it would require toggling the CSS property from:
#foo { position: relative; }
to
#foo { position: fixed; }
Or with jQuery, something like:
$('#foo').css('position', 'fixed');
Another way I have seen this implemented is with blogs, where a popup will be called when you reach the bottom, or near the bottom of a page. My question is, what is firing that code, and could you link or provide some syntax/ semantics/ examples?
Edit: I'm seeing some great JS variants coming up, but as I am using jQuery, I think the plugin mentioned will do just nicely.
Take a look at this jsfiddle: http://jsfiddle.net/remibreton/RWJhM/2/
In this example, I'm using document.onscroll = function(){ //Scroll event } to detect a scroll event on the document.
I'm then calculating the percentage of the page scrolled based on it's height. (document.body.scrollTop * 100 / (document.body.clientHeight - document.documentElement.clientHeight)).
document.body.scrollTop being the number of pixels scrolled from the top, document.body.clientHeight being the height of the entire document and document.documentElement.clientHeight being the visible portion of the document, a.k.a. the viewport.
Then you can compare this value to a target percentage, an execute JavaScript. if(currentPercentage > targetPercentage)...
Here's the whole thing:
document.onscroll = function(){
var targetPercentage = 80;
var currentPercentage = (document.body.scrollTop * 100 / (document.body.clientHeight - document.documentElement.clientHeight));
console.log(currentPercentage);
if(currentPercentage > targetPercentage){
document.getElementById('pop').style.display = 'block';
// Scrolled more than 80%
} else {
document.getElementById('pop').style.display = 'none';
// Scrolled less than 80%
}
}
If you prefer jQuery, here is the same example translated into everybody's favorite library: http://jsfiddle.net/remibreton/8NVS6/1/
$(document).on('scroll', function(){
var targetPercentage = 80;
var currentPercentage = $(document).scrollTop() * 100 / ($(document).height() - $(window).height());
if(currentPercentage > targetPercentage){
$('#pop').css({display:'block'});
//Scrolled more than 80%
} else {
$('#pop').css({display:'none'});
//Scrolled less than 80%
}
});
An idea would be to handle the window.scroll event and determine if the user has scrolled to the bottom of the page. Here is an example:
http://chrissilich.com/blog/load-more-content-as-the-user-reaches-the-bottom-of-your-page-with-jquery/
Hope it helps!
There is a jquery plugin that might help you in the right direction.
http://imakewebthings.com/jquery-waypoints/
I just answered basically the same question here. In that case it was a table and its header, and the basic idea is like this:
function placeHeader(){
var $table = $('#table');
var $header = $('#header');
if ($table.offset().top <= $(window).scrollTop()) {
$header.offset({top: $(window).scrollTop()});
} else {
$header.offset({top: $table.offset().top});
}
}
$(window).scroll(placeHeader);
Here's a demo.
Quoting myself:
In other words, if the top of the table is above the scrollTop, then
position the header at scrollTop, otherwise put it back at the top of
the table. Depending on the contents of the rest of the site, you
might also need to check if you have scrolled all the way past the
table, since then you don't want the header to stay visible.
To answer your question directly, it is triggered by checking the scrollTop against either the position of an element, or the height of the document minus the height of the viewport (for the scrolled to bottom use case). This check is done every time the scroll event is fired (bound using $(window).scroll(...)).
How can I make a div element move up and down the page when the user is scrolling the page? (where that element is always visible)
You want to apply the fixed property to the position style of the element.
position: fixed;
What browser are you working with? Not all browsers support the fixed property. Read more about who supports it, who doesn't and some work around here
http://webreflection.blogspot.com/2009/09/css-position-fixed-solution.html
Just for a more animated and cute solution:
$(window).scroll(function(){
$("#div").stop().animate({"marginTop": ($(window).scrollTop()) + "px", "marginLeft":($(window).scrollLeft()) + "px"}, "slow" );
});
And a pen for those who want to see: http://codepen.io/think123/full/mAxlb, and fork: http://codepen.io/think123/pen/mAxlb
Update: and a non-animated jQuery solution:
$(window).scroll(function(){
$("#div").css({"margin-top": ($(window).scrollTop()) + "px", "margin-left":($(window).scrollLeft()) + "px"});
});
using position:fixed alone is just fine when you don't have a header or logo at the top of your page. This solution will take into account the how far the window has scrolled, and moves the div when you scrolled past your header. It will then lock it back into place when you get to the top again.
if($(window).scrollTop() > Height_of_Header){
//begin to scroll
$("#div").css("position","fixed");
$("#div").css("top",0);
}
else{
//lock it back into place
$("#div").css("position","relative");
}
Here is the Jquery Code
$(document).ready(function () {
var el = $('#Container');
var originalelpos = el.offset().top; // take it where it originally is on the page
//run on scroll
$(window).scroll(function () {
var el = $('#Container'); // important! (local)
var elpos = el.offset().top; // take current situation
var windowpos = $(window).scrollTop();
var finaldestination = windowpos + originalelpos;
el.stop().animate({ 'top': finaldestination }, 1000);
});
});
Just add position: fixed; in your div style.
I have checked and Its working fine in my code.
You might want to check out Remy Sharp's recent article on fixed floating elements at jQuery for Designers, which has a nice video and writeup on how to apply this effect in client script