Quick: When #element reaches the top of the window

I’d like to have the following run when a certain element, say, #thiselement, reaches the top of the window.$(".sticky").unstick();Can someone please provide the code for this? I can use jquery. Thanks!

You can use the offset() method to obtain where an element is relative to the document, and you can use the scrollTop() method to figure out where the top of the document is.

If the element offset is at 1000 and scrollTop is more than 1000, you know that you’ve scrolled the element above off the screen.

Can you work things out from here?

Unfortunately not. I don’t actually know JS. I only know PHP (and am no expert, at that) so can modify some JS to suit my needs. But I can’t really write anything. Here’s what I’m using.

<script> // TABLE SCROLL & STICKY $(window).on('load', function() { $('table#comparison').each(function() { var element = $(this); var scrollWrapper = $('<div />', { 'class': 'scrollable', 'html': '<div />' }).insertBefore(element); element.data('scrollWrapper', scrollWrapper); element.appendTo(scrollWrapper.find('div')); if (element.outerWidth() > element.parent().outerWidth()) { element.data('scrollWrapper').addClass('scroll-on'); } <?php if(count($validSelections) > 1) { ?> else { $(".sticky").sticky({topSpacing:36, getWidthFrom: "#comparison", responsiveWidth: true, className: "stuck"}); } <?php } ?> $(window).on('resize orientationchange', function() { if (element.outerWidth() > element.parent().outerWidth()) { element.data('scrollWrapper').addClass('scroll-on'); <?php if(count($validSelections) > 1) { ?> $(".sticky").unstick(); <?php } ?> } else { element.data('scrollWrapper').removeClass('scroll-on'); <?php if(count($validSelections) > 1) { ?> $(".sticky").sticky({topSpacing:36, getWidthFrom: "#comparison", responsiveWidth: true, className: "stuck"}); <?php } ?> } }); }); }); </script>

I was going to give a generic example, but as you have existing code to work with here and your skills are next to nothing, that won’t do.

Further progress from here will involve getting from you enough information so that we can put together a working example ourselves, so that a complete solution can be crafted together for you.

Ah. I did not realize that it was complicated. If you’ll take a look here, and if you scroll all the way to the bottom with your window size having a small height, you’ll see that the sticky white bar never goes away. I want it to go away once the window moves past the table. The code to do it is simply $(".sticky").unstick(); but I don’t know how to run it when the window gets that far.

Well in this case, you can compare the top of the sticky with the top of the footer.

if ($('.sticky').offset().top > $('#footer-container').offset().top) {
    // hide the sticky
} else {
    // show sticky
}

Or, if you don’t want the bottom of the sticky to cross the footer, you can get the bottom of the sticky by combining the sticky top and the sticky height.

var stickyBottom = $('.sticky').offset().top + $('.sticky').height();
if (stickyBottom  > ...) {
    ...
} else {
    ...
}

The trouble is, how do arrange when to perform these comparisons. jQuery has a .scroll() handler so you can attach an event to when the document scrolls.

$(document).scroll(function () {
    // perform the sticky height test here
});

That function will then run whenever the page scrolls, allowing you to test and check if the sticky should be hidden or shown once again.

That should be enough to get you going with a solution from here.

Thank you very much! I will try this out soon.

Almost there. Thank you! So far I added this: $(document).scroll(function () { var stickyBottom = $('.sticky').offset().top + $('.sticky').height(); if (stickyBottom > $('#table-cat-OfficialWebsites').offset().top) { $(".sticky").unstick(); } });
The problem is that if I do this in order to get the sticky to come back, it gets buggy and starts flickering. $(document).scroll(function () { var stickyBottom = $('.sticky').offset().top + $('.sticky').height(); if (stickyBottom > $('#table-cat-OfficialWebsites').offset().top) { $(".sticky").unstick(); } else { $(".sticky").sticky({topSpacing:36, getWidthFrom: "#comparison", responsiveWidth: true, className: "stuck"}); } });
Edit: I think it’s because when the sticky is disabled, the if() is rendered false,which creates this endless loop. Hmm.

Tried this but no luck.$(document).scroll(function () { var stickyBottom = $('.sticky').offset().top + $('.sticky').height(); if (stickyBottom > $('#table-cat-OfficialWebsites').offset().top) { $(".sticky").unstick(); } else if($('#table-cat-OfficialWebsites').offset().top > 0) { $(".sticky").sticky({topSpacing:36, getWidthFrom: "#comparison", responsiveWidth: true, className: "stuck"}); } });

When the sticky is unstuck it moves back up to the top of the page, so its scrollTop value is going to be different from when it was stuck to the top of the screen.

What can be done about this is to remember the existing page scroll value when we need to hide it, so that we can check if the page scroll retreats back under that limit which is when we want to stick the sticky once again.

Here’s something to try out:

$(document).scroll(function () {
    var stickyBottom = $('.sticky').offset().top + $('.sticky').height(),
        scrollLimit = $('#table-cat-OfficialWebsites').offset().top;
    if (!$('.sticky').data('pageScroll')) {
        if (stickyBottom > scrollLimit) {
            $('.sticky').data('pageScroll', $('body').scrollTop());
            $(".sticky").unstick();
        }
    } else {
        if ($('body').scrollTop() < $('.sticky').data('pageScroll')) {
            $('.sticky').data('pageScroll', 0);
            $(".sticky").sticky({topSpacing:36, getWidthFrom: "#comparison", responsiveWidth: true, className: "stuck"});
        }
    }
});

That worked perfectly! Thank you very much. I really appreciate it.

There is a small issue I’m having with the other part of the JS. I’ll start a different thread on that soon.

@Paul_Wilkins
Oh, found a bug, unfortunately. I had it set up before so that if the scroll activated, the sticky would deactivate. Now I’m getting both actions, though. To see, take a look at this page and make your browser window narrow.

You may have to explain in further detail about what is wrong about things there, and what you would expect to see instead.

There are two separate scripts going on here. One allows the table to scroll horizontally if it does not fit in the window width. The other enables the sticky part. The JS should be enabling only one at a time. Now, however, both can be enabled simultaneously. See here:

Hmm. May have resolved the problem I’m working on it. Will let you know. Thanks.

@Paul_Wilkins
Okay, I think I fixed the above. Thank you for your assistance. I have one other issue, which I discussed here. Do you have any thoughts on this? It’s a pretty big problem.

<div id="undefined-sticky-wrapper" class="sticky-wrapper" style="height: 106px;"> <div id="undefined-sticky-wrapper" class="sticky-wrapper" style="height: 106px;"> <div id="undefined-sticky-wrapper" class="sticky-wrapper" style="height: 106px;"> <div id="undefined-sticky-wrapper" class="sticky-wrapper" style="height: 106px;"><

$(window).on('load', function() { $('table#comparison').each(function() { var element = $(this); var scrollWrapper = $('<div />', { 'class': 'scrollable', 'html': '<div />' }).insertBefore(element); element.data('scrollWrapper', scrollWrapper); element.appendTo(scrollWrapper.find('div')); if (element.outerWidth() > element.parent().outerWidth()) { element.data('scrollWrapper').addClass('scroll-on'); } else { $(".sticky").sticky({topSpacing:36, getWidthFrom: "#comparison", responsiveWidth: true, className: "stuck"}); } $(window).on('resize orientationchange', function() { if (element.outerWidth() > element.parent().outerWidth()) { element.data('scrollWrapper').addClass('scroll-on'); $(".sticky").unstick(); } else { element.data('scrollWrapper').removeClass('scroll-on'); $(".sticky").sticky({topSpacing:36, getWidthFrom: "#comparison", responsiveWidth: true, className: "stuck"}); } }); }); }); $(document).scroll(function () { var stickyBottom = $('.sticky').offset().top + $('.sticky').height(), scrollLimit = $('#table-cat-OfficialWebsites').offset().top; if (!$('.sticky').data('pageScroll')) { if (stickyBottom > scrollLimit) { $('.sticky').data('pageScroll', $('body').scrollTop()); $(".sticky").unstick(); } } else { if ($('body').scrollTop() < $('.sticky').data('pageScroll')) { $('.sticky').data('pageScroll', 0); $(".sticky").sticky({topSpacing:36, getWidthFrom: "#comparison", responsiveWidth: true, className: "stuck"}); } } });

I think it can be cured by making sure the code does not create a sticky wrapper more than once. Not quite sure how to do that though.

Here is the sticky code.[code]// Sticky Plugin v1.0.0 for jQuery
// =============
// Author: Anthony Garand
// Improvements by German M. Bravo (Kronuz) and Ruud Kamphuis (ruudk)
// Improvements by Leonardo C. Daronco (daronco)
// Created: 2/14/2011
// Date: 2/12/2012
// Website: http://labs.anthonygarand.com/sticky
// Description: Makes an element on the page stick on the screen as you scroll
// It will only set the ‘top’ and ‘position’ of your element, you
// might need to adjust the width in some cases.

(function($) {
var defaults = {
topSpacing: 0,
bottomSpacing: 0,
className: ‘is-sticky’,
wrapperClassName: ‘sticky-wrapper’,
center: false,
getWidthFrom: ‘’,
responsiveWidth: false
},
$window = $(window),
$document = $(document),
sticked = ,
windowHeight = $window.height(),
scroller = function() {
var scrollTop = $window.scrollTop(),
documentHeight = $document.height(),
dwh = documentHeight - windowHeight,
extra = (scrollTop > dwh) ? dwh - scrollTop : 0;

  for (var i = 0; i < sticked.length; i++) {
    var s = sticked[i],
      elementTop = s.stickyWrapper.offset().top,
      etse = elementTop - s.topSpacing - extra;

    if (scrollTop <= etse) {
      if (s.currentTop !== null) {
        s.stickyElement
          .css('position', '')
          .css('top', '');
        s.stickyElement.trigger('sticky-end', [s]).parent().removeClass(s.className);
        s.currentTop = null;
      }
    }
    else {
      var newTop = documentHeight - s.stickyElement.outerHeight()
        - s.topSpacing - s.bottomSpacing - scrollTop - extra;
      if (newTop < 0) {
        newTop = newTop + s.topSpacing;
      } else {
        newTop = s.topSpacing;
      }
      if (s.currentTop != newTop) {
        s.stickyElement
          .css('position', 'fixed')
          .css('top', newTop);

        if (typeof s.getWidthFrom !== 'undefined') {
          s.stickyElement.css('width', $(s.getWidthFrom).width());
        }

        s.stickyElement.trigger('sticky-start', [s]).parent().addClass(s.className);
        s.currentTop = newTop;
      }
    }
  }
},
resizer = function() {
  windowHeight = $window.height();

  for (var i = 0; i < sticked.length; i++) {
    var s = sticked[i];
    if (typeof s.getWidthFrom !== 'undefined' && s.responsiveWidth === true) {
      s.stickyElement.css('width', $(s.getWidthFrom).width());
    }
  }
},
methods = {
  init: function(options) {
    var o = $.extend({}, defaults, options);
    return this.each(function() {
      var stickyElement = $(this);

      var stickyId = stickyElement.attr('id');
      var wrapperId = stickyId ? stickyId + '-' + defaults.wrapperClassName : defaults.wrapperClassName 
      var wrapper = $('<div></div>')
        .attr('id', stickyId + '-sticky-wrapper')
        .addClass(o.wrapperClassName);
      stickyElement.wrapAll(wrapper);

      if (o.center) {
        stickyElement.parent().css({width:stickyElement.outerWidth(),marginLeft:"auto",marginRight:"auto"});
      }

      if (stickyElement.css("float") == "right") {
        stickyElement.css({"float":"none"}).parent().css({"float":"right"});
      }

      var stickyWrapper = stickyElement.parent();
      stickyWrapper.css('height', stickyElement.outerHeight());
      sticked.push({
        topSpacing: o.topSpacing,
        bottomSpacing: o.bottomSpacing,
        stickyElement: stickyElement,
        currentTop: null,
        stickyWrapper: stickyWrapper,
        className: o.className,
        getWidthFrom: o.getWidthFrom,
        responsiveWidth: o.responsiveWidth
      });
    });
  },
  update: scroller,
  unstick: function(options) {
    return this.each(function() {
      var unstickyElement = $(this);

      var removeIdx = -1;
      for (var i = 0; i < sticked.length; i++)
      {
        if (sticked[i].stickyElement.get(0) == unstickyElement.get(0))
        {
            removeIdx = i;
        }
      }
      if(removeIdx != -1)
      {
        sticked.splice(removeIdx,1);
        unstickyElement.unwrap();
        unstickyElement.removeAttr('style');
      }
    });
  }
};

// should be more efficient than using $window.scroll(scroller) and $window.resize(resizer):
if (window.addEventListener) {
window.addEventListener(‘scroll’, scroller, false);
window.addEventListener(‘resize’, resizer, false);
} else if (window.attachEvent) {
window.attachEvent(‘onscroll’, scroller);
window.attachEvent(‘onresize’, resizer);
}

$.fn.sticky = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === ‘object’ || !method ) {
return methods.init.apply( this, arguments );
} else {
$.error(‘Method ’ + method + ’ does not exist on jQuery.sticky’);
}
};

$.fn.unstick = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === ‘object’ || !method ) {
return methods.unstick.apply( this, arguments );
} else {
$.error(‘Method ’ + method + ’ does not exist on jQuery.sticky’);
}

};
$(function() {
setTimeout(scroller, 0);
});
})(jQuery);
[/code]

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.