Floating elements on scroll - javascript

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(...)).

Related

Hide a div until scrolled to the bottom of the page

I am making a web page (kind of like those music release pages, here is an example), and I would like certain div's at the bottom not to be shown until the user has scrolled to the bottom of the page, delay a second or two, then pop up. Kind of like a hidden feature thing.
You can also think of it like an infinite scroll, like when you drag down your Instagram feed at the top it refreshes it, and new posts show up. That's the user experience I'm looking for, only in my case it is a "finite scroll", just with some div's hidden by default.
I currently have two implementations of it, neither fully achieves the desired experience. Both used jQuery Slim.
In both implementations, #hidden is the id of my hidden-by-default div, it has style="display: none;" inline, on the div tag.
The first one looks like this:
$(window).scroll(function() {
var x = $(document).height() - $(window).height() - 20;
if( $(window).scrollTop() > x ) {
$("#hidden").delay(1000).show(0);
}
else {
$("#hidden").hide(0);
}
});
The problem with this one is that when the div shows up it changes the document height, so when you get to the bottom of the page it kind of flickers (due to recomputing the document height), and sometimes goes back to being hidden. Really bad user experience.
The second one looks like this:
$(window).scroll(function() {
if( $(window).scrollTop() > 75 ) {
$("#hidden").delay(1000).show(0);
}
else {
$("#hidden").hide(0);
}
});
This one got rid of the flickering problem by keeping the threshold static altogether, slightly better user experience, but not really flexible, in the case that my page gets longer I'll have to set a new threshold for the div to show up.
In neither of the above solutions did the delay(1000) work. The div showed up as soon as the page gets scrolled to the bottom.
Is it possible to make this design work out?
You can try this code:
$(window).on("scroll", function() {
var scrollHeight = $(document).height();
var scrollPosition = $(window).height() + $(window).scrollTop();
if ((scrollHeight - scrollPosition) / scrollHeight === 0) {
$("#hidden").delay(1000).show(0);
}
});

Fade in div once user scrolls past element

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();
}

Freeze element (position:fixed) for specific scroll range

I'm working on this site (http://styleguide.co/medhelp/) that has 5 sections. For one of the sections (Styles), I've got a sidenav I'm trying to get to stick in the visible frame only as long as users are scrolling in that section.
Here's what I've done thus far - I'm telling the section title & sidenav to stick after the top of the section has begun:
$(window).scroll(function(event) {
var sw = $('.fixed'),
pg = $('.styles'),
diff = pg[0].offsetTop - window.pageYOffset;
if (diff < 80 ) {
$('.fixed').css('position', 'fixed');
$('.fixed').css('top', '160px');
$('.styles').css('position', 'fixed');
$('.styles').css('top', '70px');
}
else {
$('.fixed').css('position', 'relative');
$('.fixed').css('top', '0px');
$('.styles').css('position', 'relative');
$('.styles').css('top', '0px');
}
});
I can't seem to figure out a good way to make the section title "Style" and the sidenav appear/disappear while I scroll to/from that section. Any advice? What could I do better? A simple solution demo in jsfiddle would really help!
Please click on this link & scroll down/up to know what I'm referring to: http://styleguide.co/medhelp/
I'm not going to give you a fiddle, but you need to determine when the next section would stick based on its offset from the top. At the moment what you are doing is:
// if difference top and element < 80 -> fix to top, else position is relative
First of all this means the condition will never be undone. What you need to do in order to continue is:
// once next contact section comes into screen
//(offset from the top of the screen <= screen height), give
var winHeight = $(window).height();
var calcTop = 80 - (winHeight - (winHeight - $('#nextSelector').offset().top);
$('.fixed').css('top', calcTop);
This will give the illusion of your text scrolling up as the new section comes up. I hope this helps. Also, when scrolling back up it doesn't re-stick, but you probably are aware of that.

Changing div postion depending on page scroll

I have the following code below that changes a div's position to fixed once an element scrollTop is greater than a number. I am trying to either amend this script or find a different solution so that the div will scroll between a range and STOP scrolling at some point ( so the div doesn't go off the page or overlap with footer elements.
I don't know if the right way is to say that IF scrollTop is greater than 150 then position=fixed, and if it's greater than 600 then position goes back to absolute, or if there's a better way, like distance from the bottom...
AND I use MooTools, not jQuery. I know there are a few jQuery options / plugins that do this. Thanks in advance!
window.onscroll = function()
{
if( window.XMLHttpRequest ) { // IE 6 doesnt implement position fixed nicely...
if (document.documentElement.scrollTop > 150) {
$('tabber').style.position = 'fixed';
$('tabber').style.top = '0';
} else {
$('tabber').style.position = 'absolute';
$('tabber').style.top = 'auto';
}
}
}
the script above is wrong on many levels.
don't use window.onscroll but window.addEvent("scroll", function() {});
cache selectors. using $("tabber") 3 times on each scroll when the element does not change is expensive.
just do var tabber = $("tabber") and reference that.
you don't need to do
$("tabber").style.position = ...
$("tabber").style.top = ...
do:
tabber.setStyles({
position: "fixed",
top: 12123,
right: 24
});
There are mootools plugins for this, eg scrollSpy by David Walsh: http://davidwalsh.name/mootools-scrollspy
it can allow you to set scripted events upon reaching various scrolling destinations or events, look at the examples.
or you could just write it yourself, eg, this took me 15 mins to do:
http://jsfiddle.net/dimitar/u9J2X/ (watch http://jsfiddle.net/dimitar/u9J2X/show/) - it stops being fixed when it reaches to 20 px of the footer. and then goes back to fixed if scrolling up again.

fixed div on bottom of page that stops in given place

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!

Categories