I have a little problem with one code.
The html:
<div id="navigation">
<ul>
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
</ul>
</div>
Simple CSS, just to show the problem:
* { margin: 0; padding: 0; }
.shell { width: 960px; margin: 0 auto; }
#navigation { background: red; height: 18px; }
#navigation ul { float: left; display: inline; }
#navigation ul li { float: left; display: inline; }
#navigation ul li a { float: left; display: inline; font-size: 14px; line-height: 18px; color:#000; }
#navigation ul li a:hover { background:blue; }
And the JS(using jQuery)
var padWidthModule = ($('#navigation').width() - $('#navigation ul').width())%$('#navigation ul li').length,
padWidthParse = parseInt(($('#navigation').width() - $('#navigation ul').width())/$('#navigation ul li').length),
padHalfWidthModule = padWidthParse%2,
padHalfWidthParse = parseInt(padWidthParse/2),
module = (padWidthModule + padHalfWidthModule)%2;
moduleParse = parseInt((padWidthModule + padHalfWidthModule)/2);
if (padHalfWidthModule==0) {
$('#navigation ul li a').css({
'paddingLeft': padHalfWidthParse,
'paddingRight': padHalfWidthParse
})
}else{
$('#navigation ul li a').css({
'paddingLeft': padHalfWidthParse,
'paddingRight': padHalfWidthParse+1
})
}
if (module == 0) {
$('#navigation ul li:last a').css({
'paddingLeft': padHalfWidthParse+moduleParse,
'paddingRight': padHalfWidthParse+moduleParse
})
}else {
$('#navigation ul li:last a').css({
'paddingLeft': padHalfWidthParse+moduleParse,
'paddingRight': padHalfWidthParse+moduleParse+1
})
}
setTimeout(function() {
var liSum = 0,
pixelDifference = 0;
if($('#navigation ul li:first').position().top != $('#navigation ul li:last').position().top){
$('#navigation ul li').each(function(){
liSum += $(this).outerWidth(true);
})
pixelDifference = $('#navigation').width()-liSum;
console.log(liSum)
$('#navigation ul li:last a').css({
'paddingLeft': padHalfWidthParse+moduleParse-pixelDifference
});
}
}, 1);
Pretty much the code should add dynamically padding to the navigation elements in order to fill the navigation width, without no white spaces.
The problem you ask?
The code is tested under IE6,IE7.IE8,IE9,Safari,Opera,Chrome and works fine with no problem…but the problem is coming from FireFox under Windows 7 and MAC (there is no problem under XP).
In firefox the last element falls under the navigation. If you see in the JS I added just for that a setTimeout function, that it’s only purpose is to fix the buggy FireFox.
But there is more, I left a console.log(liSum) that calculate the width of all the "li" elements after the JS put it’s padding to them and it should show you 597px (under FireFox).
So we have 3px difference that is substracted from the last element…
But lets stop here, doesn’t this sound fishy? We have a box with width 960px, and list elements with sum 957px, who seem that can’t fit in the box…? If my math is right 957<960 so they should fit after all…but nope… (you should notice, that if the problem was that the width of the elements are bigger than 960px I would had substracted their width and the width of the navigation, but this isn’t the case)
So after the substract you will see that there is still some space after the last navigation element. (actually I can hard code it and substract 1 from the last item, that look better, but there will be still some space left)
If the setTimeout is removed, the last element will fall, but if we opened FireBug and remove just 1px from the last element, it will snap to the navigation box, but there will be still a little space at the end.
Any ideas if this is fixable? (and where is the problem coming from)
(sorry if my english is bad)
jsFiddle: http://jsfiddle.net/utWda/
Screens:
(bad) FireFox Win7 (with setTime function): http://i.imgbox.com/adoAy24C.jpg
(bad) FireFox Win7 (without setTime): http://i.imgbox.com/ads6Ldvu.jpg
(good) Opera: http://i.imgbox.com/acqkLzGy.jpg
(good) FireFox XP: http://i.imgbox.com/abudcEOp.jpg
Your problem is presumably that jQuery is screwing you over.
The way it’s doing that is that jQuery’s
width()returns widths rounded to the nearest pixel. But actual widths of CSS boxes don’t have to be integer numbers of pixels. In your case, say each link has a width that’s 0.45px greater than an integer. Then if the sum of the widths after you round them to the nearest pixel is 3px less than your total width, the sum of all 7 link widths will actually be 0.15px larger than the total width, and things will break, as you discovered.To fix this, you should use getBoundingClientRect() for size calculations. And complain to the jQuery developers to fix jQuery’s
width()…