Centre widthless floats.... like these:

It is normally stated that you cannot centre floated elements but this is not quite true. It's true that usually you can only float left or float right but if you have a group of buttons for a menu and you want them to be fluid in width then it would be nice to have them all float in the centre of the page. There is no problem if the floats have a width because you can then ascertain the main parents width and use margin:auto to center the whole block. However that means that the floats cannot be a fluid width (i.e. shrinkwrap their content) or you would have to class each individual element and apply a different width to each which is a little unsatisfactory.

So how can this be achieved more simply then?

The premise is simple and basically just involves a widthless float wrapper that is floated to the left and then shifted off screen to the left width position:relative; left:-50%. Next the nested inner element is reversed and a relative position of +50% is applied. This has the effect of placing the element dead in the center. Relative positioning maintains the flow and allows other content to flow underneath.

Code:

#buttons{
float:right;
position:relative;
left:-50%;
text-align:left;
}
#buttons ul{
list-style:none;
position:relative;
left:50%;
}

#buttons li{float:left;position:relative;}/* ie needs position:relative here*/

#buttons a{
text-decoration:none;
margin:10px;
background:red;
float:left;
border:2px outset blue;
color:#fff;
padding:2px 5px;
text-align:center;
white-space:nowrap;

}
#buttons a:hover{ border:2px inset blue;color:red;background:#f2f2f2;}
#content{overflow:hidden}/* hide horizontal scrollbar*/

The above demo should work in most modern browsers and will work in ie5 - 7. (It doesn't work in ie5 mac but you can achieve a similar effect using display:inline-block instead of floats so view source for the full details .)

Here is another example using the same technique

Drawbacks

The drawbacks are mainly that when the floats wrap at shorter screen-widths then the element that has wrapped will not align to the center. That doesn't seem to be much of a problem to me but you may think differently. In a fixed width scenario there will of course be no need to wrap and will work fine.

You should also take care that the negative shift doesn't overlay anything to the side (left side) but this can simply be cured by adding overflow:hidden to the main parent. It will not be an issue if here is nothing to the left (such as a side column).

The same techniques could most likely be applied to absolute elements as their behaviour of shrink-wrapping contents is the same as floats. However absolute elements would be removed from the flow so its not so useful

Another Option

We can achieve a similar effect by not using floats but using display:table for Mozilla/Opera and using display:inline-block for all IE. IE only understands display:inline-block on inline elements but fortunately if you first make the block level element display:inline-block and then declare it as display:inline in the next style block it now treats the block level element as display:inine-block. This is also consistent in ie7 and IE8 has proper support for inline-block anyway.

Note: The actual mechanism for this to work is that any inline element that is in "haslayout" mode will be treated as inline-block. See my inline-block article for the full rundown on why and how this works.

Also note that there is a long standing gecko bug when using display:table and in most cases you would need to include and intermediary element set to display:table-row or on first load the page may be broken.

<style type="text/css">

.navcentre {
margin:10px auto;
display:table;
border:1px solid #000;
padding:2px;
white-space:nowrap;
}
.navcentre ul {
list-style:none;
margin:0;
padding:0;
display:table-row;
white-space:nowrap;
}

.navcentre ul li{
display:table-cell;
}
.navcentre ul a{
display:block;
padding:4px 10px;
text-decoration:none;
background:#ffffcc;
border:1px solid #ff0000;
}
.navcentre ul a:hover{background:red;color:#fff}

</style>
<!--[if lt IE 8]>
<style type="text/css">
.navcentre ul {display:inline-block;}
.navcentre ul{display:inline; }
.navcentre ul li{display:inline-block}
.navcentre ul li{ display:inline;}
.navcentre ul a{ display:inline-block;}
.navcentre{text-align:center}
</style>
<![endif]-->

As usual use at your own risk and test thoroughly on the platforms you want to support. Any problems or improvements then email me at paul@pmob.co.uk although I can't guarantee to answer all emails.