Search code examples
javascriptjquerytwitter-bootstrapsticky-footer

Twitter Bootstrap - Update Affix Data-Offset attribute on the fly


I am using a "sticky footer" technique for an area on the page which also has a navbar utilizing affix. The problem is the data-offset attribute needs to get updated depending on where the sticky footer is - thus it cannot be hard-coded.

How to I get the value in pixels of where the sticky footer is, and pass that value into the data-offset attribute so it knows when to affix itself?

Any help would be greatly appreciated!


Solution

  • I am also fixing navbar depending on position that cannot be hardcoded into css. Not because of an sticky footer, but just space above navbar (when not fixed) is dynamic, but I suppose the solution is similar.

    I am using JavaScript to fix/unfix by setting/unsetting proper classes dynamicaly depending if some DOM element is visible on viewport. The scheme is as follows:

    • navbar is styled with position: absolute and the space containing it has static height of navbar, so there is no change of position of a content below when fixing,
    • bind the function that spies the scrolling and fixes navbar if the element above is not visible,
    • check if element is visible by comparing the bottom of its position with the top of position of the viewport,
    • fix/unfix by adding/removing bootstrap classes each time the user scrolls or change the size of window.

    The code in Opa framework (converting to JS+jQuery should be straightforward as Opa's DOM library is just simple binding to jQuery):

    // id of the element above the navbar, and the navbar
    logobar_id = "logo-bar";
    navbar_id = "main-menu";
    // hardcoded height of the navbar
    navbar_height_px = 30;
    
    client function distance() {
      dom = #{logobar_id};
    
      // hardcoded height of the navbar
      win = Dom.select_window();
    
      // position of the top of the viewport
      scroll_visible = Dom.get_scroll_top(win);
    
      // return the distance between of bottom of element above the navbar and the top of 
      dom_bottom = Dom.get_offset(dom).y_px + Dom.get_height(dom);
      dom_bottom - scroll_visible;
    }
    
    dom = #{navbar_id};
    
    private client function fixation() {
      if (distance() <= 0) {
        // TODO: remember if subnav is fixed, dont fix if fixed
        Dom.add_class(dom, "navbar-fixed-top");
        Dom.remove_class(dom, "container");
      } else {
        // TODO: remember if subnav is fixed, dont unfix if unfixed
        Dom.remove_class(dom, "navbar-fixed-top");
        Dom.add_class(dom, "container");
        void;
      }
    }
    
    // (un)fix when scroll
    private client function onscroll(_) {
      fixation();
    }
    
    // bind the `onscroll` handler for subnav when it is loaded
    private client function onready(_) {
      _ = Dom.bind(Dom.select_window(), {scroll}, onscroll);
      fixation();
    }
    

    The DOM element above the navbar and the navbar itself:

    <div class="container" id=#{logobar_id}>
      My logo with dynamic content
    </div>
    <div class="container" style="height: {navbar_height_px}px; position: relative; top: 0px">
      <div style="position: absolute; top: 0px">
        <div class="navbar container" id=#{navbar_id} onready={onready}>
          ...
        </div>
      </div>
    </div>