Add class when element is at top of window - javascript

I'm trying to create sticky headers that when you scroll to a div the head state becomes fixed and stays in view, when the div has come to an end and scrolls out of view I want the title to then become absolute and stay at the bottom of its parent.
I've got the initial part working only I'm struggling on adding the 'absolute' class...
https://jsfiddle.net/yw313vf2/1/
function fixTitle() {
$('.service-pane').each(function() {
var $this = $(this);
var offset = $this.offset().top;
var scrollTop = $(window).scrollTop();
if (scrollTop > offset) {
$this.addClass('fixed');
} else {
$this.removeClass('fixed');
}
});
}
$(window).scroll(fixTitle);

So I had to run another check within the function to see if when scrolled the end of my div had reached the top of the window and if so add an additional class...
function fixTitle() {
$('.service-pane').each(function() {
var $this = $(this);
var offset = $this.offset().top - 50;
var scrollTop = $(window).scrollTop();
if (scrollTop > offset) {
$this.addClass('fixed');
if ($this[0].getBoundingClientRect().bottom < $('.manifesto').height() + 50) {
$this.addClass('absolute');
} else {
$this.removeClass('absolute');
}
} else {
$this.removeClass('fixed');
}
});
}

Related

Scrolling sidebar inside a div with scrollbar - $(window).on('scroll', function()?

I want my social sidebar make scroll only within the gray div. I have already put the sidebar within the gray div does not exceed the footer or the content above. My difficulty is to sidebar scroll accompanying the scroll without going gray div.
http://test.eae.pt/beautyacademy/angebot/
JS:
beautyAcademy.sharer = {
element: void 0,
elementToScroll: void 0,
init:function() {
this.element = $('.js-sharer-ref');
console.log(this.element.length);
if(this.element.length != 1) {
return;
}
this.build();
},
build: function() {
this.binds();
},
binds: function() {
var _this = this;
// Element that's gonna scroll
this.$elementToScroll = $('.fixed-social');
// Element that's gonna scroll height
this.elementToScrollHeight = this.$elementToScroll.outerHeight();
// Element where scroll is gonna happen Height
this.elementHeight = this.element.outerHeight();
// Element where scroll is gonna happen distance to top
this.elementOffsetTop = this.element.offset().top;
// Scroll that was done on the page
this.windowScrollTop = $(window).scrollTop();
this.elementOffsetBottom = this.elementOffsetTop + this.elementHeight - this.elementToScrollHeight;
this.$elementToScroll.css('top', (_this.elementOffsetTop+80) + "px");
$(window).on('scroll', function() {
if(this.windowScrollTop + this.elementToScrollHeight < this.elementHeight )
this.$elementToScroll.css('margin-top', this.windowScrollTop );
});
}
};
You need to try like below :
$(function(){
if ($('#container').length) {
var el = $('#container');
var stickyTop = $('#container').offset().top; // returns number
var stickyHeight = $('#container').height();
$(window).scroll(function(){ // scroll event
var limit = $('#footer').offset().top - stickyHeight - 20;
var windowTop = $(window).scrollTop(); // returns number
if (stickyTop < windowTop){
el.css({ position: 'fixed', top: 0 });
}
else {
el.css('position','static');
}
if (limit < windowTop) {
var diff = limit - windowTop;
el.css({top: diff});
}
});
}
});
DEMO

How to find Multiple div reach top?

I have a survey page divided into sections. As the user scrolls, each section's header sticks to the top of the screen until the next section is reached. I was able to do it for the first and second section but I am not sure how to do it for the third one. There must be a better way to do this.
Here is my code and a jsfiddle
Thank you
var s = $("#block2 .question-title-block");
var pos = s.position();
$(window).scroll(function() {
var windowpos = $(window).scrollTop();
if ($(this).scrollTop() > 404) {
$('#block1 .question-title-block').addClass("sticky");
if (windowpos >= pos.top) {
$('#block2 .question-title-block').addClass("sticky");
$('#block1 .question-title-block').removeClass("sticky");
}
else{
$('#block2 .question-title-block').removeClass("sticky");
}
}
else{
$('#block1 .question-title-block').removeClass("sticky");
$('#block2 .question-title-block').removeClass("sticky");
}
})
If you want it to be applied to as many elements as you want, don't use them individually, use their class. Here is what you can do:
var titleBlocks = $(".question-title-block");
$(window).scroll(function() {
var windowpos = $(window).scrollTop();
titleBlocks.each(function(){
$(this).toggleClass('sticky', $(this).parent().offset().top <= windowpos);
});
});
JS Fiddle Demo
try this (allows for any number of question blocks):
var containers = $('.question-block-container');
$(window).scroll(function () {
var windowpos = $(window).scrollTop();
containers.each(function () {
var container = $(this),
title = container.find('.question-title'),
contOffsetTop = container.offset().top,
conOffsetBottom = contOffsetTop + container.outerHeight() + 60; // 60 is margin bottom
if (windowpos >= contOffsetTop && windowpos <= conOffsetBottom) {
if (!title.hasClass("sticky")) {
title.addClass("sticky");
}
} else if (title.hasClass("sticky")) {
title.removeClass("sticky");
}
});
});
Example

jQuery - sticky element is overlapping the footer, how to avoid it?

I have a sticky sidebar working on my project, but when you go to the bottom of the page, the sticky sidebar is overlapping my footer.
What I want is that when the sticky element reach the footer, then stop just right there so the user can see the entire footer.
here is a demonstration of what I have so far.
or a jsfiddle in case it is easier for you
this is the code:
var stickySidebar = $('.sticky');
if (stickySidebar.length > 0) {
var stickyHeight = stickySidebar.height(),
sidebarTop = stickySidebar.offset().top;
}
// on scroll move the sidebar
$(window).scroll(function () {
if (stickySidebar.length > 0) {
var scrollTop = $(window).scrollTop() + 70;
if (sidebarTop < scrollTop) {
stickySidebar.stop(true, false).animate({top: scrollTop - sidebarTop});
// stop the sticky sidebar at the footer to avoid overlapping
var sidebarBottom = stickySidebar.offset().top + stickyHeight,
stickyStop = $('.main-content').offset().top + $('.main-content').height();
if (stickyStop < sidebarBottom) {
var stopPosition = $('.main-content').height() - stickyHeight;
stickySidebar.stop(true, true).animate({top: stopPosition});
}
}
else {
stickySidebar.stop().animate({top: 0});
}
}
});
$(window).resize(function () {
if (stickySidebar.length > 0) {
stickyHeight = stickySidebar.height();
}
});
This is maybe not perfect, but I think it gives you the right idea, how to solve this problem. You just have to check, if the bottom of the sidebar is below the top position of the footer. Than stop the animation.
http://jsfiddle.net/hdj99b21/1/
[...]
var stickyTopPos = stickySidebar.offset().top;
var stickyBottomPos = stickyHeight + stickyTopPos;
var footerTopPos = $('footer').offset().top;
if(stickyBottomPos >= footerTopPos) {
var stopPosition = footerTopPos - stickyHeight;
stickySidebar.stop(true, true).css({top: stopPosition});
}
[...]

Sticky Sidebar that only sticks when sidebar bottom is at window bottom

I have a 2 column layout. The left column is way longer than the sidebar. I want the sidebar only to stick when its bottom reaches the bottom of the browser window. So the user can continue to scroll down the left column content while the right sidebar sticks. I've seen a lot of sticky questions here, however this particular situation still stumps me. I also have a sticking headline bar on the left column that i've successfully gotten to stick.
Here's a demo of what I've done in jsfiddle!
and here's a quick look at the js I am trying out.
$(function(){
var headlineBarPos = $('.headlineBar').offset().top; // returns number
var sidebarHeight = $('.sticky-sidebar-wrap').height();
var sidebarTop = $('.sticky-sidebar-wrap').offset().top;
var windowHeight = $(window).height();
var totalHeight = sidebarHeight + sidebarTop;
$(window).scroll(function(){ // scroll event
var windowTop = $(window).scrollTop(); // returns number
// fixing the headline bar
if (headlineBarPos < windowTop) {
$('.headlineBar').addClass('sticky').css('top', '0');
}
else {
$('.headlineBar').removeClass('sticky').removeAttr('style');
}
if(sidebarHeight < windowTop) {
$('.sticky-sidebar-wrap').addClass('sticky').css('top', '0');
} else {
$('.sticky-sidebar-wrap').removeClass('sticky').removeAttr('style');
}
console.log(windowTop);
});
console.log(headlineBarPos);
console.log(sidebarHeight);
console.log(sidebarTop);
});
I hope I got it right, when the bottom of the sidebar comes into the view, then stick?
I created another div at the bottom of the sidebar (inside the sidebar).
When that comes into view, it sticks.
http://jsfiddle.net/Z9RJW/10/
<div class="moduleController"></div> //inside the sidebar
and in js
$(function () {
var headlineBarPos = $('.headlineBar').offset().top; // returns number
var moduleControllerPos = $('.moduleController').offset().top; // returns number
var sidebarHeight = $('.sticky-sidebar-wrap').height();
var sidebarTop = $('.sticky-sidebar-wrap').offset().top;
var windowHeight = $(window).height();
var totalHeight = sidebarHeight + sidebarTop;
$(window).scroll(function () { // scroll event
var windowTop = $(window).scrollTop(); // returns number
// fixing the headline bar
if (headlineBarPos < windowTop) {
$('.headlineBar').addClass('sticky').css('top', '0');
} else {
$('.headlineBar').removeClass('sticky').removeAttr('style');
}
if (moduleControllerPos < windowTop + windowHeight) {
$('.sticky-sidebar-wrap').addClass('sticky').css('top', '0');
} else {
$('.sticky-sidebar-wrap').removeClass('sticky').removeAttr('style'); }
console.log(windowTop);
});
console.log(headlineBarPos);
console.log(sidebarHeight);
console.log(sidebarTop);
});
I hope it helps.
Something like:
if (sidebar.top + sidebar.height < window.scrolltop + window.height) {
// set sticky
}
and set sticky needs to take into account that the sidebar may be higher than the viewport, so:
sidebar.top = sidebar.height - window.height // this will be a negative number

Getting a floating div to stop upon reaching another div

I have a floating div on the sidebar that scrolls with the page. Is there a way to add code that makes it stop when it reaches the footer?
See code in action: http://openbayou.staging.wpengine.com
jQuery code used to float div:
$j=jQuery.noConflict();
$j(document).ready(function($) {
//this is the floating content
var $floatingbox = $('#one');
if($('#primary').length > 0){
var bodyY = parseInt($('#primary').offset().top) - 20;
var originalX = $floatingbox.css('margin-left');
$(window).scroll(function () {
var scrollY = $(window).scrollTop();
var isfixed = $floatingbox.css('position') == 'fixed';
if($floatingbox.length > 0){
$floatingbox.html();
if ( scrollY > 1561 && !isfixed ) {
$floatingbox.stop().css({
position: 'fixed',
top: 10,
});
} else if ( scrollY < 1561 && isfixed ) {
$floatingbox.css({
position: 'relative',
top: 0,
});
}
}
});
}
});
Why not just set the z-index of the sidebar behind the z-index of the footer?
EDIT: I didn't like the result of this so I went and made this work in jquery the way you want it...
try this for your scroll function:
$(window).scroll(function () {
floatingbox = $("#one");
if(floatingbox.length > 0){
//get our current scroll position
var scrollY = $(window).scrollTop();
//get the position of the tag cloud relative to the document
var contentY = ($("#sidebar .sidebar-tag-cloud").offset().top + $("#sidebar .sidebar-tag-cloud").outerHeight(false));
//calculate the largest possible top margin size before it starts to overlap the footer
var lastY = $("#footer").offset().top - $("#one").outerHeight(false);
//check if our scroll location is past the bottom of the tag cloud
if ( scrollY > contentY )
{
//check if the current top position is less than the maximum position
if(floatingbox.offset().top<lastY)
{
//keep scrolling
floatingbox.stop().animate({"marginTop":scrollY-contentY});
}else
{
//check if we have scrolled back up and have a space at the top
if(scrollY<floatingbox.offset().top)
{
floatingbox.stop().animate({"marginTop":scrollY-contentY});
}else
{
// hard set to the maximum position
floatingbox.stop().css({"marginTop":lastY-contentY});
}
}
}
}
});
I also made it a little more dynamic by getting the location of the bottom of the tag cloud and using that instead of your hard-coded number.
Alright, after looking at your latest jsfiddle. I have modified that code to work with yours. http://jsfiddle.net/Tgm6Y/4430/ This will not have the animate lag and should work well for you.
$('#one').followTo('#two','#pointFive');
just replace #two with #footer and #pointFive with "#sidebar .sidebar-tag-cloud" and this should work in your code.
UPDATE: Found a solution to my problem.
$(function () {
var msie6 = $.browser == 'msie' && $.browser.version < 7;
if (!msie6) {
var top = $('#one').offset().top;
$(window).scroll(function (event) {
var y = $(this).scrollTop() + 20;
if (y >= top) {
$('#one').addClass('fixed');
}
else {
$('#one').removeClass('fixed');
}
// don't overlap the footer - pull sidebar up using a negative margin
footertotop = ($('#footer').position().top);
scrolltop = $(document).scrollTop() + 760;
difference = scrolltop - footertotop;
if (scrolltop > footertotop) {
$('#one').css('margin-top', 0 - difference);
}
else {
$('#one').css('margin-top', 0);
}
});
}
});
What this does is it stops before the footer and I can configure the stopping point.
I appreciate all the help in solving my problem!

Categories

Resources