Two Loon Software & Web Development
  541.708.1488

jQuery Fixed Table Headers

I'm a fan of fixed elements. I'm a fan of elements that become fixed when they reach the top of the browser. I use fixed positioning often and I am glad that it's started to become more popular thanks to Google and Twitter.

That being said, I ran into an interesting use case today: fixed table headers. If the table has fixed with columns this is trivial (the same as fixing any other element). However, if the table is full width and the column widths are dynamic, the widths will be lost when you apply position:fixed to the header row.

I've written a jQuery plugin that handles the fixing of the header and the resizing of the table headers. It assumes you are using appropriate table/theader/tr/th markup.


Javascript

(function ($){ 
    $.fn.extend({
        FixMe: function (options) {
            this.defaultOptions = {};
            var settings = $.extend({}, this.defaultOptions, options);
            return this.each(function () {
                var $this = $(this);
                $(document).scroll(function () {
                    if (!$this.attr('data-top')) {
                        if ($this.hasClass('subnav-fixed')) return;
                        var offset = $this.offset()
                        $this.attr('data-top', offset.top);
                    }
                    if ($this.attr('data-top') - $this.outerHeight() <= $(this).scrollTop()) {
                        $headerCells = $this.find('th');
                        $firstCells = $this.closest('table').find('tr:last td');

                        for (var i = 0; i < $headerCells.length; i++) {
                            $($headerCells[i]).width($($firstCells[i]).width());
                        }

                        if($this.parent().find('.clone').length == 0){
                        $this.parent().append($this.clone().addClass('clone'));
                        $this.addClass('aves-subnav-fixed');
                        }
                    }
                    else {
                        $this.find('th').width('auto');
                        $this.removeClass('aves-subnav-fixed');
                        if($this.parent().find('.clone').length > 0){
                            $this.parent().find('.clone').remove();
                        }  
                    }
                });
                $(window).resize(function() {
                    if($this.hasClass('aves-subnav-fixed')){
                        $headerCells = $this.find('th');
                        $firstCells = $this.closest('table').find('tr:last td');

                        for (var i = 0; i < $headerCells.length; i++) {
                            $($headerCells[i]).width($($firstCells[i]).width());
                        }
                    }
                });
            });
        }
    });
})(jQuery);

CSS

This CSS is required:
.aves-subnav-fixed
	{
		position:fixed;
		top:0px;
		width:100%;
		z-index:9999;
	}
This CSS optional. It gives the fixed header a nice drop shadow:
.aves-subnav-fixed th
	{
	    -webkit-box-shadow: 3px 3px 17px rgba(50, 50, 50, 0.38);
	    -moz-box-shadow:    3px 3px 17px rgba(50, 50, 50, 0.38);
	    box-shadow:         3px 3px 17px rgba(50, 50, 50, 0.38);
	    background:white;
	}

Usage

$('table theader').FixMe();
< All Code Articles
logo

Welcome to Two Loon Software

Sorry, our website doesn't support your web-browser.
Maybe something more modern would do the trick.

download chrome