David Somekh
David Somekh

Reputation: 933

Sticky table headers with firefox / IE

I am using a div with display:table and I am trying to create sticky headers. Chrome supports position:sticky with display:table-row but firefox and IE do not. Therefore, I created a code that changes the div position to "fixed" on scroll and the top to 0. This gets the same result.

However, when changing the position to "fixed" the header row stops being a part of the table and therefore it's width is changed. (And is no longer synced with the other table rows)

I tried to fix it with saving the width of each column and then setting it again, but that's extremely buggy.

I am looking for a solution that will allow me to change the position to "fixed" but will not change the top row width and it will stay connected with the rest of the table.

Any ideas?

$(window).scroll(function() 
{
  	if (window.pageYOffset >= $('.table').offset().top) 
	{
		$('.row_header').css('position','fixed');
		$('.row_header').css('top',0);
	}

	else
	{
	
		$('.row_header').offset({ top: $('.table').offset().top});
		$('.row_header').css('position','static');
		
		//console.log('satic');
	}

});
.wrapper{

padding:10px;


 
  display:flex;
  justify-content:center;
  align-items:center;
}

.table{
  display:table;
  margin: 0 0 40px 0;
 max-width: 100%;
  
}

.row {
  display: table-row;

}

.cell {
  display: table-cell;
  border:1px solid black;
  padding:2px;


}

.row_header {
	display: table-row;

 background: #ADD8E6;


}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script>

<p align=center><b>Scroll to see the problem...</b>
<div class="wrapper">
<div class="table">
	<div class="row_header">
		<div class="cell">Name</div>
		<div class="cell">Age</div>
		<div class="cell">Site</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	<div class="row">
		<div class="cell">David</div>
		<div class="cell">33</div>
		<div class="cell">Stack overflow</div>
	</div>
	
	
	
	
</div>
</div>

Upvotes: 1

Views: 5296

Answers (1)

scooterlord
scooterlord

Reputation: 15349

Well, here goes, this is a tough one, however here is the solution, I have previously spent a lot of time on this one. :/

First of all you add two span elements inside the .row_header:

  • .static is used for cases where the header cell is a lot longer than the rest of the content. If this element didn't exist, the .fixed element would be as long as the largest cell width in that column. If it was shorter than the cell content, it would overflow to the next cell.
  • .fixed is used to make the header content sticky.

As soon as the DOM loads and the table renders, you calculate the cell sizes from each column as they are arbitrarily rendered by the table. In the example I calculate from the .row_header - it doesn't matter since it is rendered alongside all the table content in the first place. Then you apply this width on the span elements inside the .row_header.

The rest I took from you. It's a bit late and am a bit tired, but I am sure you can avoid the arbitrarily set negative margin to align the .fixed spans. However, the whole idea and implementation is here.

Here is a working fiddle:

https://jsfiddle.net/k7ep2Lq0/1/

Upvotes: 2

Related Questions