Let me start of by saying, I'm just now learning JS and Jquery, so my knowledge is very limited.
I've been looking around for 2 days now, and tried all sorts of combinations. But I just can't get this to work.
Below is an example of the layout
I'm looking for a way to trigger an event when div 1 is X px from the top of the screen. Or when div 1 collides with div 2.
What I'm trying to accomplish is to change the css of div 2 (the fixed menu) when div 1 is (in this case) 100px from the top of screen (browser window). Alternatively, when div1 passes div2 (I'm using responsive design, so the fixed height from top might become a problem on smaller screens right? Seeing as the header for example won't be there on a hand held.). So maybe collision detection is better here? Would really appreciate some thoughts and input on this matter.
Another issue is, div2 has to revert back to is previous css once div1 passes it (going back (beyond the 100px)).
This is what I have but it has no effect
$(document).ready(function() {
var content = $('#div1');
var top = $('#div2');
$(window).on('scroll', function() {
if(content.offset().top <= 100) {
top.css({'opacity': 0.8});
}else{
top.css({'opacity': 1});
}
});
});
I am not sure of the reason but $("#content").offset().top was giving a constant value on console. So I added window.scrollTOp() to check its distance from top, here is how it works,
$(document).ready(function() {
var top = $("#menu");
$(window).on('scroll', function(){
if(($('#content').offset().top - $(window).scrollTop()) <= 100){
top.css({'opacity': 0.4});
}else{
top.css({'opacity': 1});
}
});
});
And DEMO JSFIDDLE....
Related
I need to know if the end of a div element is currently visible in the users' browser.
I tried something I saw on the web, but scrollTop() always gave me zero in my Browser. I read something about an issue in Chrome, but I didn't understand quite well.
jQuery(
function($) {
$('#flux').bind('scroll', function() {
if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
alert('end reached');
}
})
}
);
My idea is the following:
1- User loads page and sees a Bar (sticky div at bottom visible page) with some information.
2- After scrolling a bit, and reaching the end of a div element, this bar will position there, after the div. This is the bar's original position
I wasn't really able to know when I was at the end of the div element. Eventually I found this code:
if ($(window).scrollTop() >= $('#block-homepagegrid').offset().top + $('#block-homepagegrid').outerHeight() - window.innerHeight) {
$('.hero-special-message').removeClass('hero-special-messege-scrolling');
} else {
$('.hero-special-message').addClass('hero-special-messege-scrolling');
}
});
I see that it's working, but I'm having a bit of trouble understanding what it does.
I know the following:
1. $(window).scrollTop();
this gives me the amount of pixels the user has scrolled, pretty self explanatory.
2. $('#block-homepagegrid').offset().top;
I THINK this is the distance between the start of the page and the start of the div. I know it's the current coordinates, but what is top exactly here?
3. $('#block-homepagegrid').outerHeight();
this gives the height of the element, I know there are 3, like
height(), innerHeight() and outerHeight(), if you want to take into
account border, margin, padding, which is the better to use?
4. window.innerHeight;
I understand this is what the user sees, but I'm having troubles understanding why does it matter for my situation.
Thanks!
You may be interested in the native JavaScript IntersectionObserver API. It automatically figures out what percentage of a given element is visible in the window and triggers callbacks based on that. So then you can do this:
function visibleHandler(entries) {
if (entries[0].intersectionRatio >= 1.0) {
// The whole element is visible!
} else {
// Part of it is scrolled offscreen!
}
}
const observer = new IntersectionObserver(visibleHandler, {threshold: 1.0});
observer.observe(document.getElementById('flux'));
Now, whenever the element with ID flux is 100% in view, it will trigger the visibleHandler. It will also trigger again if it's scrolled back out of view; that's why the function checks the ratio of visibility to see if it just hit 100% or just got reduced from 100%. You could be more fancy and use the observer entry's insersectionRect, which gives you the rectangle containing the visible portion of the element, and use that to determine top/bottom visibility.
I'm making a slide scrolling page, and I'm trying to have it scroll like you're pulling a notecard up and with the next one right behind it.
To do this, I'm making them all fixed, and then moving their "top" position based off of scroll. But then I also need to make the body the size of the panel.
It's hard to describe what I'm doing, so here's the demo: https://codepen.io/NotDan/pen/vzraJE
Here's the particular piece of code that's causing my problem:
//what's going on here?
$(window).scroll(function(){
var panelNum = parseInt($(window).scrollTop()/$(window).height());//detemines panel number
var pixelMovement = ($(window).scrollTop())-(panelNum*$(".panel").height()); determines how many pixels to move the panel by
$('body').find(".panel:eq("+panelNum+")").css("top", -1*pixelMovement);
});
The problem is when the user scrolls quickly, the top position is not set accurately and there's some overhang. Again, hard to explain, but if you jump to the demo and scroll quickly you'll see what I mean.
Is there a more precise way of measuring scroll? Or is there a better way to do what I'm trying to? I've tried scrollmagic, and its "section wipe" feature is really close, but they bring the previous one up rather than move the current one up.
I tried making a condition to determine the panel number and everything started working.
var panelNum = 0;
var pixelMovement = 0;
$(window).scroll(function () {
pixelMovement = $(window).scrollTop() - panelNum * $(".panel").height(); // determines how many pixels to move the panel by
$("body")
.find(".panel:eq(" + panelNum + ")")
.css("top", -1 * pixelMovement);
if (Math.abs(pixelMovement) >= $(window).height()) {
panelNum++;
} else if (pixelMovement <= 0) {
panelNum--;
}
});
Here's the working demo: https://codepen.io/NotDan/pen/RYJeZq
I have seen various forms of this problem but nothing really helped me to solve the partial sticky sidebar/Bootstrap column behaviour. Let me start with the problem itself.
There is a big image close to the top of my page. Because of the page complexity, I am using Bootstrap column grid. The image spans over, let's say, 10 columns and I have left 2, belonging to the same row, on the left side to store a sidebar. This also allows me to vertically align the sidebar next to the image.
Now, the sidebar, what is now a Bootstrap column, should go sticky and should stay vertically aligned to the viewport once the scrollbar passes by. You can see in the fiddle that it kind of "jumps" instead of transitioning smoothly.
The other problem is that the sticky element/column should only remain sticky as long as its parent/container is visible. Which means that it should transition/be relative to the end of that container. Right now I have only managed to keep it sticky till the end of the page. It should stop above the red line (depicted in the fiddle).
Here is my jQuery logic so far.
$(document).ready(function(){
$(window).scroll(function(){
var elem = $("#refScroller").offset().top - ($("#refScroller").height() / 2);
var windowvalue = $(window).scrollTop();
if (elem <= windowvalue) {
$("#wannabeSticky").addClass("sticky");
}
else {
$("#wannabeSticky").removeClass("sticky");
}
});
});
I would really appreciate some ideas and hints as this has been bothering me for two days. I would love to keep the Bootstrap grid structure if possible, but feel free to give any suggestions, even those who depict the sidebar as a pure absolute div, as long as the sticky-ness works.
Thanks in advance!
EDIT: I know there is a similar problem already here, but it seems I can't make the JS logic work for my case.
So, having spent another day on it, it seems I reached a decent jQuery version that gets the job done. There is my updated fiddle.
$(document).ready(function(){
var passedMobileNavi = false;
function stickySocialNavi(reference, valueExtracted) {
var refTop = $(reference).offset().top - valueExtracted;
var scrollTop = $(window).scrollTop();
return (refTop <= scrollTop);
}
$(window).scroll(function() {
if (stickySocialNavi($("#refScroller"), $("#refScroller").height())) {
if (!passedMobileNavi) {
passedMobileNavi = true;
$("#wannabeSticky").addClass("sticky");
}
}
else {
passedMobileNavi = false;
$("#wannabeSticky").removeClass("sticky");
}
if (stickySocialNavi($("#end"), $(window).height())) {
var var1 = $(window).scrollTop(),
var2 = $("#end").offset().top,
var3 = $(window).height();
var calculateOffset = (var2 - var3) - var1;
$("#wannabeSticky").css("top", "calc(50% + " + calculateOffset + "px)");
}
else {
$("#wannabeSticky").css("top", "50%");
}
});
});
For the sticky-ness to start, I took the reference point (which is the non-moving element right next to it) and its height. The sticky element gets a fixed position as long as the scrollbar goes past the reference point's center.
As the stick element is centered, it gets additional top offset values when the end of its container is reached. It is still fixed, but its top property's value takes the scroll difference, thus slowly depicting it towards the end of the container.
I don't know if this is the most elegant, straightforward, or easy to implement/understand solution, but it worked for me.
My goal is to make a fixed div appear at the top of a page once someone scrolls a certain amount of pixels down the page. Basically once the header section is out of view, this div will appear.
I've looked at code similar to what I want; however, haven't seen anything that would allow me to easily modify the pixel count from the top of the page (if possible).
Here is a piece of code I saw dealing with making divs appear by scrolling.
// Get the headers position from the top of the page, plus its own height
var startY = $('header').position().top + $('header').outerHeight();
$(window).scroll(function(){
checkY();
});
function checkY(){
if( $(window).scrollTop() > startY ){
$('.fixedDiv').slideDown();
}else{
$('.fixedDiv').slideUp();
}
}
// Do this on load just in case the user starts half way down the page
checkY();
I just want to know how to make it appear. If someone knows of a piece of code already in tact with a slide up and slide down animation, that would be greatly appreciated as well but not required.
window.addEventListener("scroll",function() {
if(window.scrollY > 500) {
$('.fixedDiv').slideDown();
}
else {
$('.fixedDiv').slideUp();
}
},false);
Brandon Tilley answered my question in a comment...
You would change the first line, with the startY, to be the specific Y
position you need, rather than calculating based on the header's
position and height. Here's an updated fiddle:
jsfiddle.net/BinaryMuse/Ehney/1
window.addEventListener("scroll",function() {
$('.fixedDiv')[(window.scrollY > 500)?"slideDown":"slideUp"]();
},false);
DEMO: http://jsfiddle.net/DerekL/8eG2A/
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.