Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 4 of 4
  1. #1
    New to the CF scene
    Join Date
    Mar 2014
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts

    How can I add a class of "bottom" to "#sidebar" once it reaches a certain point?

    I'm using the code below which adds a class of "fixed" to "#sidebar" once it reaches a certain height from the top of the site depending on what page it's on (i.e. home, single, page).

    In a similar fashion, I would like to add a class of "bottom" to "#sidebar" once "#sidebar" reaches the bottom of its container ("#content"). If the user scrolls back up, the class of "bottom" should be removed and the class of "fixed" should be added back.

    The goal is to try to get the fixed sidebar to move up with the rest of the content in its container once it reaches the bottom of it.

    Here's an animation of something similar:



    JavaScript

    Code:
    var threshold = 236;
    if (jQuery(document.body).hasClass("home")) {
      threshold = 654;
    } else if (jQuery(document.body).hasClass("single") || jQuery(document.body).hasClass("page")) {
      threshold = 20;
    }
    
    var scrolled = false;
    jQuery(window).scroll(function () {  
      if (jQuery(window).scrollTop() >= threshold && !scrolled){
        jQuery('#sidebar').addClass('fixed');
        scrolled = true;
      } else if (jQuery(window).scrollTop() < threshold && scrolled) { 
        jQuery('#sidebar').removeClass('fixed');
        scrolled = false;
      }
    });
    HTML

    Code:
    <div id="container">
    
      <div id="content">
    
        <div id="sidebar"></div>
    
        <div id="masonry"></div>
    
      </div>
    
    </div>
    I've been trying to figure this out and now my head hurts lol. I would appreciate any help with this. Thank you.

  • #2
    The fat guy next door VIPStephan's Avatar
    Join Date
    Jan 2006
    Location
    Halle (Saale), Germany
    Posts
    8,917
    Thanks
    6
    Thanked 1,040 Times in 1,013 Posts
    This is a little more intricate than you might think because not only does it require to calculate a bottom point, you also need to keep the viewport size in mind, horizontally as well as vertically.
    I’ve done something like this on this site (the book on the left stays fixed) and on this site (the navigation on the left; here I also had the challenge that the height of the nav is changing when opening and closing items (click the plus/minus)). The relevant JS for the book functionality on the first site is in this file starting at line 589 and going to line 667 (I need to note that on lines 30–36 I’m setting up the window size calculations). For the second example I can’t even tell you any specific lines because there was much more to it than the left navigation (e. g. the header also stays fixed etc.).

    But first things first: For a bottom trigger you need to calculate the height of the document, the height of the viewport, the height of the element you are positioning, and the height of the footer, if you have one. The first thing you need to consider is the possibility of the viewport being smaller than the element. In that case you don’t want to position it fixed at all because otherwise people will never be able to access content that is outside the viewport. Therefore you need to dynamically calculate the viewport height (and possibly document height, too, if you have other dynamic content that changes it) while resizing the viewport.
    So, here is some pseudo code to get the logic straight:

    PHP Code:
    // this calculation needs to take place statically on load (in case page is already scrolled somewhere in the middle when loading) as well as dynamically on resize
    if(viewport height > (element height possible top margin)) { // only change position to “fixed” if viewport is larger than element
      
    if((window scroll position element height possible top margin) > (document height footer height)) { // if scroll position is far down at the bottom
        
    remove fixed position
        change to absolute position with top value 
    = (content height element height)
      }
      else {
        
    add fixed position
      
    }
    }
    else { 
    // viewport is smaller than element
      
    remove fixed position

    That’s this for the vertical position.
    But by applying a fixed position the element is positioned relative to the viewport, so if you resize your viewport horizontally it might cover other content. So, in order to do it right you also need to calculate the viewport/window width, and the left/right position of the element. But we can do this afterwards if you got the vertical positioning working, it’s too much explaining for me right now.
    Last edited by VIPStephan; 03-23-2014 at 01:07 PM.

  • #3
    Senior Coder
    Join Date
    Mar 2005
    Location
    Portsmouth UK
    Posts
    4,534
    Thanks
    3
    Thanked 513 Times in 500 Posts
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    
    <head>
      <title></title>
    <style type="text/css">
    /*<![CDATA[*/
    
    #sidebar {
      position:fixed;z-Index:101;right:5px;top:50px;width:100px;height:600px;background-Color:blue;
    }
    
    #footer {
      position:absolute;left:0px;top:1500px;width:1230px;height:500px;background-Color:red;
    }
    
    /*]]>*/
    </style></head>
    
    <body>
    <div id="sidebar" >Sidebar</div>
    <div id="footer" ></div>
    
    <script type="text/javascript">
    /*<![CDATA[*/
    
    var zxcSidebar={
    
     init:function(o){
      var sb=document.getElementById(o.SidebarID),f=document.getElementById(o.FooterID);
      if (sb&&f){
       o.sb=sb;
       o.st=sb.offsetTop;
       o.f=f;
       this.addevt(window,'scroll','scroll',o);
       this.scroll(o);
      }
     },
    
     scroll:function(o){
      var f=this.ft(o.f),s=window.innerHeight?window.pageYOffset:document.documentElement.clientHeight?document.documentElement.scrollTop:document.body.scrollTop;
      var ud=o.st+s+o.sb.offsetHeight<f
      if (ud!=o.ud){
       o.sb.style.position=ud?'fixed':'absolute';
       o.sb.style.top=(ud?o.st:f-o.sb.offsetHeight)+'px';
      }
      o.ud=ud;
     },
    
    
     ft:function(o){
      var r=0;
      while(o){
       r+=o.offsetTop;
       o=o.offsetParent;
      }
      return r;
     },
    
     addevt:function(o,t,f,p,p1){
      var oop=this;
      o.addEventListener?o.addEventListener(t,function(e){ return oop[f](p,p1);},false):o.attachEvent?o.attachEvent('on'+t,function(e){ return oop[f](p,p1); }):null;
     }
    
    }
    
    zxcSidebar.init({
     SidebarID:'sidebar',
     FooterID:'footer'
    });
    
    /*]]>*/
    </script>
    
    </body>
    
    </html>
    Vic

    God Loves You and will never love you less.

    http://www.vicsjavascripts.org/Home.htm

    If my post has been useful please donate to http://www.operationsmile.org.uk/

  • #4
    New to the CF scene
    Join Date
    Mar 2014
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thank you. I've worked the ideas given by you guys into my own code and I've come really close to what I need: However, for some reason, the "bottom" class gets added way too early causing the sidebar to jump to the bottom before it even hits the footer. Can someone take a look and let me know what I've overlooked?

    I implemented this into a test site I'm working on.

    JS
    Code:
    jQuery(window).scroll(function () {
        var threshold = 654;
    
        if (jQuery(window).scrollTop() >= threshold)
            jQuery('#sidebar').addClass('fixed');
        else
            jQuery('#sidebar').removeClass('fixed');
        var check = jQuery('#content').height() - jQuery('#sidebar').height();
        if (jQuery(window).scrollTop() >= check)
            jQuery('#sidebar').addClass('bottom');
        else
            jQuery('#sidebar').removeClass('bottom');
    });
    CSS
    Code:
    #sidebar {
      margin: 0;
      position: absolute;
      right: 0;
      width: 220px;
    }
    #sidebar.fixed {
      margin-left: 720px;
      position: fixed;
      right: auto;
      top: 173px;
    }
    #sidebar.bottom {
      bottom: 0;
      top: auto;
      position: absolute;
    }


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •