Reputation: 3619
I have some table headers which I planned on making sticky (fixed) as the user scrolls down the page, but they currently shrink when the sticky is activated, I would like them to inherit the widths of the headers, but they shrink to the size of the text at the moment. My JS:
$(document).ready(function() {
var stickyNavTop = $('.th').offset().top;
SOLUTION:
$(".th th").each(function(){$(this).width($(this).width());});
$('.th').width($('.th').width());
var stickyNav = function(){
var scrollTop = $(window).scrollTop();
if (scrollTop > stickyNavTop) {
$('.th').addClass('sticky');
} else {
$('.th').removeClass('sticky');
}
};
stickyNav();
$(window).scroll(function() {
stickyNav();
});
});
My HTML:
<table class="mGrid" cellspacing="0" rules="all" border="1" id="1"
style="width:98%;border-collapse:collapse;">
<tr class="th">
<th scope="col">Membership No.</th>
<th scope="col">Surname</th>
<th scope="col">Other Name(s)</th>
</tr>
<tr>
<td>
<div id="2" class="formInput">
<label for="2">Membership No.</label>
<input name="2" type="text" value="AH6973" id="2"
class="required" style="width:60px;" />
</div>
</td>
<td>
<div id="3" class="formInput">
<label for="3">Surname</label>
<input name="3" type="text" value="CARTER" id="3"
style="width:100px;" />
</div>
</td>
<td>
<div id="4" class="formInput">
<label for="4">Other Name(s)</label>
<input name="4" type="text" value="RAYMOND" id="4"
style="width:150px;" />
</div>
</td>
</tr>
</table>
my CSS:
.sticky {
position: fixed;
width: 100%;
top: 0;
z-index: 100;
border-top: 0;
color: #fff !important;
background: #666;
border-left: solid 1px #525252;
font-size: 1.0em;
}
(This is modelled to be the same as the header style, it's just the width shrinks to fit the width of the text at the moment. I tried to edit the header style but it's apparently read-only "'HeaderStyle' property is read-only and cannot be set."
Upvotes: 6
Views: 4964
Reputation: 343
Just add this line before your function definition:
$('th').width($('th').width());
Full JavaScript code:
$(document).ready(function() {
var stickyNavTop = $('.th').offset().top;
$('th').width($('th').width());
var stickyNav = function(){
var scrollTop = $(window).scrollTop();
if (scrollTop > stickyNavTop) {
$('.th').addClass('sticky');
} else {
$('.th').removeClass('sticky');
}
};
stickyNav();
$(window).scroll(function() {
stickyNav();
});
});
Upvotes: 6
Reputation: 5431
My solution to avoid column width changes : cloning the header. (Thanks to @Matt for the line: $('th').width($('th').width());
and his solution.)
JS
var stickyNavTop = jQuery('thead tr:first-child').offset().top;
// init state
var stickState = (jQuery(window).scrollTop() > stickyNavTop);
var stickyNav = function() {
var scrollTop = jQuery(window).scrollTop();
// state has changed?
if (stickState != (scrollTop > stickyNavTop)) {
// remember/catch new state
stickState = (scrollTop > stickyNavTop);
if (stickState) {
jQuery('thead tr:first-child th').each(
function() { jQuery(this).width( jQuery(this).width() ); }
);
// cloning the header : the original columns won't move
jQuery('thead tr:first-child')
.clone()
.prependTo(jQuery('thead'))
.addClass('sticky');
} else {
jQuery('tr.sticky').remove();
}
}
};
jQuery(window).scroll(function() {
stickyNav();
});
stickyNav();
CSS
.sticky {
position: fixed;
top: 0;
z-index: 100;
}
Upvotes: 1
Reputation: 4989
here is a common solution, it auto detects each sub-element's width and height and reflect when scrolling, it is something like following:
var $this = $(this),
top = $this.offset().top,
left = $this.offset().left,
width = $this.width(),
height = $this.height(),
widthArr = [],
heightArr = [];
$this.find("*").each(function(i, e) {
widthArr.push($(this).width());
heightArr.push($(this).height());
});
$(window).scroll(function() {
if($(window).scrollTop() >= top) {
$this.css({
position: "fixed",
top: 0,
left: left,
"z-index": 100,
width: width,
height: height
});
$this.find("*").each(function(i, e) {
$(this).width(widthArr[i]);
$(this).height(heightArr[i]);
});
} else {
// to be implemented
}
});
Upvotes: 1