sticky scrolling headers example

sticky scrolling headers

by ampersand

HTML

<div id="sticky-list">
  <ul>
    <li>
      <strong>Section Headline 1</strong>
      <ul>
        <li>
        <table>
            <tbody>
                <tr>
                    <td>1</td>
                    <td>2</td>
                </tr>
                <tr>
                   <td>3</td>
                   <td>4</td>
                </tr>
                <tr>
                   <td>3</td>
                   <td>4</td>
                </tr>
                <tr>
                   <td>3</td>
                   <td>4</td>
                </tr>
                <tr>
                   <td>3</td>
                   <td>4</td>
                </tr>
                <tr>
                   <td>3</td>
                   <td>4</td>
                </tr>
            </tbody>
        </table>   
       </li>
      </ul>
    </li>
    <li>
      <strong>Section Headline 2</strong>
      <ul>
        <li>
        <table>
            <tbody>
                <tr>
                    <td>1</td>
                    <td>2</td>
                </tr>
                <tr>
                   <td>3</td>
                   <td>4</td>
                </tr>
            </tbody>
        </table>            
        </li>
      </ul>
    </li>
    <li>
      <strong>Section Headline 4</strong>
      <ul>
        <li>
        <table>
            <tbody>
                <tr>
                    <td>1</td>
                    <td>2</td>
                </tr>
                <tr>
                   <td>3</td>
                   <td>4</td>
                </tr>
                <tr>
                    <td>5</td>
                    <td>6</td>
                </tr>
            </tbody>
        </table>  
        </li>
      </ul>
    </li>
  </ul>          
</div>

CSS

/* Reset some list defaults for all lists */        
ul { 
  list-style: none; 
  margin: 0;
  padding: 0;
}

/* The main container */
#sticky-list  {
  height: 100px;
  overflow: hidden;
  position: relative;
}

/* The main list */
#sticky-list > ul {
  height: 100%;
  overflow: auto;
}

/* Section headers, defined through "headlineSelector" */
#sticky-list > ul > li strong {
  display: block;
}

/* Section headers when "sticky", defined through "stickyClass" */
#sticky-list > ul > li.sticky strong {
  position: absolute;
  left: 0;
}

 ul { 
      list-style: none; 
      margin: 0;
      padding: 0;
    }
    
    #sticky-list  {
      height: 200px;
      overflow: hidden;
      position: relative;
    }
    
    #sticky-list > ul {
      height: 100%;
      overflow: auto;
    }
    
    #sticky-list > ul > li strong {
      font-size: 1.5em;
      color: #222;
      background: #ccc;
      display: block;
      padding: 0.5em 10px;
      color: #fff;
      text-shadow: 0px -1px 0px #000;
      opacity: .75;
      background-image: -webkit-gradient(
        linear,
        left top,
        left bottom,
        color-stop(0, #646262),
        color-stop(0.5, #484848),
        color-stop(0.5, #3D3D3D),
        color-stop(1, #4C4C4C)
      );
      background-image: -moz-linear-gradient(
        center top,
        #646262 0%,
        #484848 50%,
        #3D3D3D 50%,
        #4C4C4C 100%
      );
      background-image: linear-gradient(
        center top,
        #646262 0%,
        #484848 50%,
        #3D3D3D 50%,
        #4C4C4C 100%
      );
    }
    
    #sticky-list > ul > li.sticky strong {
      position: absolute;
      top: 0;
    }
    
    #sticky-list > ul ul li {
      padding: 1em 10px;
      border-bottom: 1px solid #ccc;
    }

table {
    width:100%;
}

table td {
    width:100%;
    display:block;
    border-bottom:1px solid #ddd
}

JavaScript

(function($){
  $.fn.stickySectionHeaders = function(options) {
  
    var settings = $.extend({
      stickyClass     : 'sticky',
      headlineSelector: 'strong'
    }, options);

    return $(this).each(function() {
      var $this = $(this);
      $(this).find('ul:first').bind('scroll.sticky', function(e) {
        $(this).find('> li').each(function() {
          var $this      = $(this),
              top        = $this.position().top,
              height     = $this.outerHeight(),
              $head      = $this.find(settings.headlineSelector),
              headHeight = $head.outerHeight();
              
          if (top < 0) {
            $this.addClass(settings.stickyClass).css('paddingTop', headHeight);
            $head.css({
              'top'  : (height + top < headHeight) ? (headHeight - (top + height)) * -1 : '',
              'width': $this.outerWidth() - $head.cssSum('paddingLeft', 'paddingRight')
            });
          } else {
            $this.removeClass(settings.stickyClass).css('paddingTop', '');
          }
        });
      });
    });
  };

  /* A little helper to calculate the sum of different
   * CSS properties
   *
   * EXAMPLE:
   * $('#my-div').cssSum('paddingLeft', 'paddingRight');
   */
  $.fn.cssSum = function() {
    var $self = $(this), sum = 0;
    $(arguments).each(function(i, e) {
      sum += parseInt($self.css(e) || 0, 10);
    });
    return sum;
  };
  
})(jQuery);

$('#sticky-list').stickySectionHeaders({
  stickyClass     : 'sticky',
  headlineSelector: 'strong'
});