skip to Main Content

I have an element that is a fixed position:

.woocommerce #content div.product div.summary {
    position: fixed;
    right: 15%;
    padding: 20px;
    background-color: #ccc;
    width: 25%;
}

and what I am trying to do is get the element to stop right before the footer, I have tried the following:

$(document).scroll(function (){
  if($('.woocommerce #content div.product div.summary').offset().top + $('.woocommerce #content div.product div.summary').height() >= $('footer').offset().top - 10){
    $('.woocommerce #content div.product div.summary').css('position', 'absolute');
  }

  if($(document).scrollTop() + window.innerHeight < $('footer').offset().top){
    $('.woocommerce #content div.product div.summary').css('position', 'fixed');
  } 
});

But I am getting some odd behaviour as in, it goes right to the top and the element gets much smaller in width and I have no idea how to fix it.

Here is my page I am trying to do it in…

http://handyman-ondemand.com/product/electrical/

4

Answers


  1. One way to avoid the footer from going over that div.summary is to add a margin top to footer which is the height of that div.

    #footer {
        margin-top: 500px;
    }
    
    Login or Signup to reply.
  2. Edit = Currently having 2nd thoughts about your intent, did you remove the problematic code from link?

    Remove all Javascript, totally unecessary for what you’re attempting to achieve 🙂

    The reason it won’t “stay” down there properly is because you don’t have more posts on the front page, those themes are meant to work properly once fully active.

    But obviously it’s fair of you to not want anything more on homepage.
    Add those three attributes to the class :

    woocommerce #content div.product div.summary (line #720 of your main theme CSS)

        width: 100%;
        bottom: 0px;
        position: relative;
    

    Make sure you either put them last in the class or remove doubled attributes.

    You can see originally it has a width of width: 49.9%; probably intended to have a second box of same type side by side. Most mordern browsers end up self-generating the correct full width, but obviously not ideal, best to declare 100%.

    Position relative and bottom 0px will take care of keeping it down inside it’s parents div.

    Hope that worked for you !

    ps: always privilege scallable solutions (%, vw, vh, ..) over fixed size (pixels), you’ll thank me later when realizing all browsers aren’t created equal 🙂

    enter image description here

    Login or Signup to reply.
  3. If I understand you right this is a perfect job for Intersecion Observer (IO). With IO you can react to elements overlapping with other elements or with the viewport. You can define when this observer should be triggered, when the intersection starts/ends or even before that.

    To use IO you first have to set the options for when you want IO to get triggered. I don’t 100% get your question but if you want the element to stop right before the footer, you would need to set your root to your footer.

    let options = {
      root: document.querySelector('footer'),
      rootMargin: '0px',
      threshold: 1.0
    }
    
    let observer = new IntersectionObserver(callback, options);
    

    Then you specify which element you want to watch for an intersection with your footer:

    let target = document.querySelector('.woocommerce #content div.product div.summary');
    observer.observe(target);
    

    Last step is to define the function that’s getting called once the elements overlap:

    let callback = (entries, observer) => { 
      entries.forEach(entry => {
        // Each entry describes an intersection change for one observed
        // target element
      });
    };
    

    You can also use this polyfill from w3c to support older browsers

    Login or Signup to reply.
  4. Please check your calculations. Calculate correct range with height of elements and window.height.
    Your “fixed” positioned element should be root level. (Cross Browser issue)

    Run code on this page. TargetElementSelector is footer in this example. You need to change it.

    (function() {
      var mainElement = "main_element_id";
      var targetElementSelector = "#footer";
      jQuery(targetElementSelector).height(500); // if the footer's height is low to work with
    
      var mainElementMaxTopPosition = jQuery(targetElementSelector).offset().top - jQuery(targetElementSelector).height();
    
      var html = '
        <div id="' + mainElement + '" 
            style="position: fixed;width: 250px;height: 250px;left: 0;right: 0;margin: auto;top: 0;bottom: 0;
        background: red;z-index: 99;border: 1px solid black;">
      </div>';
      jQuery('body').prepend(html);
    
      jQuery(window).scroll(function() {
        var current = jQuery(window).scrollTop() + (jQuery(window).height() / 2);
    
        if (current >= mainElementMaxTopPosition) {
    
          var topPosition = (jQuery(targetElementSelector).offset().top - jQuery('#' + mainElement).height());
    
          jQuery('#' + mainElement).css({
            position: "absolute",
            bottom: "auto",
            top: topPosition + "px"
          });
    
        } else {
    
          jQuery('#' + mainElement).css({
            position: "fixed",
            bottom: "0",
            top: "0"
          });
    
        }
      });
    })();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search