javascript examples Freeze Header until Irrelevant(HTML, CSS and JS)




transition css (3)

I have a few different tables that I want to display vertically down a page. The trouble is, the different tables have different column headings.

In the picture, the dark border represents the viewport. The dotted red border is where the red header belongs but note that it is "frozen" to the top of the viewport. This is true until, in the second image, the green header begins to replace it. http://imagebin.org/172108

Does anyone know how this could be accomplished using very lightweight scripting (In other words, I don't want JQuery or something) and CSS. I have the advantage that I only need it to render on Webkit (which means some css3 is also an option). I don't care if the headers are not actually part of the html <table> - they must obviously just line up properly though.


This will only be possible with Javascript - I can't think of a way of doing it simply with CSS.

The basis of the answer is to use position:fixed on the element. I would suggest cloning the thead of your table to attach in a fixed position at the top of the table, and then add an event listener for the scroll event and check the position of each table against the amount that has been scrolled.

I've put up an example on JSFiddle.


For what it's worth:

There are a couple of answers here but I don't think they actually answer the question. They don't operate on table headers (thead elements) or they use 3rd party libraries. There are some subtle issues with lifting a thead out of the table - the largest of which is that the cells will collapse down if the header text is wider or narrower than the data in the tbody.

Here is my solution that solves the problem without any libraries and working on table headers. It makes no assumptions about the styling of the table, or the size of the headers; everything is calculated. Only tested in Chrome per the requirements of the OP.

Script:

function initFloatingHeaders() {
  var tables = document.querySelectorAll('table.float-header');
  var i = tables.length;

  while (i--) {
    var table = tables[i];
    var wrapper = document.createElement('div');
    wrapper.className = 'floating-header';
    var clone = table.cloneNode(true);
    wrapper.appendChild(clone);
    table.parentNode.insertBefore(wrapper, table);

    var thead = table.querySelector('thead');
    wrapper.style.width = thead.scrollWidth + 'px';  
    wrapper.style.height = thead.scrollHeight + 'px';
    wrapper.style.left = table.offsetLeft + 'px';     
  }

  window.addEventListener('scroll', function() {
    var headers = document.querySelectorAll('div.floating-header');
    var bodyHeight = document.body.offsetHeight;
    var i = headers.length;
    while (i--) {
      var header = headers[i];
      var tableBounds = header.nextSibling.getBoundingClientRect();
      if (tableBounds.top < 0 && tableBounds.bottom > 0) {
        header.style.display = 'block';
      } else {
        header.style.display = null;
      }
    }
  }, false);
}

Tables should have the class float-header applied and initFloatingHeaders should be called on load or documentReady. Example: http://jsbin.com/ulusit/2 (Old example with bad transitions: http://jsbin.com/ulusit/)


edit: http://jsfiddle.net/BCtP8/3/

There, I fixed the hiccuping text. When the header becomes fixed, I change the placholder's height. I also changed it to work with any header height, not just the one I had given them.

OLD POST Here you go man:

http://jsfiddle.net/BCtP8/

Sorry for any problems that might occur, I'm quite new to the whole web developing scene and I don't have the experience to predict what might happen.

I doubt this is the best or most efficient way to do it, so if you find better, please post it here so I can learn. Thanks.





webkit