Forum Moderators: not2easy

Message Too Old, No Replies

Centered Floats - Not!

but nearly.. center those inline blocks instead.

         

SuzyUK

11:45 am on Mar 10, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



This might be a little bit exciting, well in a geeky CSS kinda way ;)

An often asked question is: Can I center floats

The answer is no you can't, best you can do is center the container that holds them.

However In order to get the blocks of "floated" content to center you would need to to use Inline Blocks
CSS2.1: display: inline-block; [w3.org].


inline-block
This value causes an element to generate a block box, which itself is flowed as a single inline box, similar to a replaced element. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an inline replaced element.

But so far only Opera correctly supports display: inline-block; IE only supports it on inline elements, such a <a> <span>. <em> which is no use for then nesting block level content inside it.

or does it? I think I've discovered another IE oddity which forces Block Level elements to honour: display: inline-block; :o

Test Case Example:

<style type="text/css" media="screen">
span, div {background: #eee; border: 1px solid #000;}
span, div {width: 300px; height: 50px;}
.ib {display: inline-block;}

/* IE if it gets the rule in two parts will correctly display as inline-block */
.ibh {display: inline-block;}
.ibh {display: inline;}

</style>
</head>
<body>
<span>span text as a normal won't accept width/height</span><span>span text as a normal won't accept width/height</span>
<hr />
<span class="ib">span text as an inline-block it now accepts a width and height</span><span class="ib">span text as an inline-block it now accepts a width and height</span>
<hr />
<div class="ib">div text normal inline-block - accepts width/height but doesn't display inline</div><div class="ib">div text normal inline-block - accepts width/height but doesn't display inline</div>
<hr />
<div class="ibh">div text with IE inline-block hack</div><div class="ibh">div text with IE inline-block hack</div>

The above code is for testing in IE only, but the code in red is the bit that is weird, setting it out in two seperate rules like that seems to make it work. This used in conjunction with the * html hack or a conditional is quite useful!

Now all that's left is FF. It doesn't support inline-block at all and display: table-cell; just will not cut it as it will shrink the blocks of content to fit on one row, (like it should, just like a table) unless rows breaks ( <tr>'s ) are specified which defeats the purpose. However Gecko/Moz does offer some proprietary code, so if you're prepared to use some non-validating code then there is a way!

-moz-inline-block is not very well supported, is very buggy and somewhere along the line FF stopped supporting it anyway. But there is another: -moz-inline-box. This works across all of the Gecko versions I tested in, the one drawback it had was that it needed a nested div of the same width as the box or the content overruns the inline-box.

So I'm gonna throw this code out for some testing: test code for a fluid "gallery" style layout

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1"></meta>
<title>Centered Floats - Gallery Style Listing</title>
<style type="text/css" media="screen">html, body {padding: 0; margin: 0; border: 0; background: #00f;}
#container {
background: #fff;
margin: 0 150px;
border: 1px solid #f00;
padding: 5px;
text-align: center;
}

.box {
display: -moz-inline-box; /* For FF */
display: inline-block; /* IE <8 needs this tripped back to display: inline; to make it work on blocks */
width: 150px;
background: #eee;
margin: 5px;
border: 1px solid #000;
text-align: left; /* to left align text within divs when container has been set to center */
vertical-align: top; /* explicitly declare as Moz inline-box auto aligns top */
}

.box div {width: 150px;} /* nested block element for FF or text runs out of -moz-inline-box */
.box p {margin: 0.5em;}
</style>

<!--[if lt IE 8]>
<style type="text/css" media="screen">
.box {display: inline;} /* this is to make inline-block work <IE8 */
</style>
<![endif]-->

</head>
<body>
<div id="container">
<div class="box"><div><p>test<br />test.</p></div></div>
<div class="box"><div><p>test</p></div></div>
<div class="box"><div><p>test</p></div></div>
<div class="box"><div><p>test.<br />test.<br />test.<br />test.<br />test.</p></div></div>
<div class="box"><div><p>test</p></div></div>
<div class="box"><div><p>test</p></div></div>
<div class="box"><div><p>test</p></div></div>
<div class="box"><div><p>test</p></div></div>
<div class="box"><div><p>You have to have the content in these boxes nested<br />inside a nested block elements with a width = to box width or this will happen in FF.</p></div></div>
</div>
</body>
</html>

Drawbacks:
The content inside the box has to be nested inside a block element with a width on it for gecko or it overruns it's inline-box.

I tried to get the blocks left aligning inside a flexible width centered container (dependant on the amount of blocks displayed), where I centered an inline-block container using the same method as above so it's width would be fluid depending on browser resolution, but FF definitely fell down on this one as it needs a width on that nested div.

Have a play let me know.. should work for text images etc.. the only thing you won't be able to do is set the height of the blocks to be dependant on each other like table cells. SO.. let me know what else you think, drawbacks or other..

Suzy

[edit]CSS updated to reflect ie7 and ie8 support[/edit]

[edited by: SuzyUK at 11:36 am (utc) on Mar. 17, 2008]

BlobFisk

12:26 pm on Mar 10, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Excellent post SuzyUK - thanks!

BlobFisk runs off to experiment with this...

limbo

12:34 pm on Mar 10, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Iv'e been looking for a replacement for the div that's wraps em all: <div align="center" id="ironlung">, for ages. As I understand this attribute is depricated so this is exciting ;)

Ooocha! I owe you a pint

SuzyUK

1:17 pm on Mar 10, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



hmm. note: I've made a typo in that second test code..

<div class="box"><div><p>You have to have the content in these boxes nested<br />inside a nested block elements with a width = to box width or this will happen in FF.</p></div></div>

You need to remove the div nested in div.box to see where FF falls down when you just use -moz-inline-box without it..:

for testing it should be:

<div class="box"><p>You have to have the content in these boxes nested<br />inside a nested block elements with a width = to box width or this will happen in FF.</p></div>

<-- me still experimenting too.. but I'll take you up on that pint limbo.. I'm thirsty ;)

Suzy

createErrorMsg

1:58 pm on Mar 10, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Suzy, this is beautiful. Excellent post! :)

The content inside the box has to be nested inside a block element with a width on it for gecko or it overruns it's inline-box.

I tried removing that <div> and instead placed it's width setting on the children of the box...

.box > * {width: 150px;}

Since IE ignores the child selector, it's auto-enclosing doesn't stretch the .boxes and break the float rows, which it would do with the width right on the <p>, due to the margin. I know Opera also understands the child selector, but I can't recall if it auto-encloses like IE...? I don't have Opera to test with on this machine, so I'll have to rely on someone else to check it if they want/can.

Was only able to test on IE6 and Firefox. Still looking into it, but if putting the width directly on the contents of the div fixes FF's problems, that *could* make the extra markup (<div>) unnecessary.

cEM

[added}I'm getting problems when adding more than one element to a box. I added a list and a paragraph to one box, but it's rendering them side-by-side, as if floating or inline, and not stacked as block level elements. It has something to do with my child selector, because it doesn't happen in Suzy's original post...still testing.[/added]

SuzyUK

9:09 pm on Mar 10, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



cEM:
but if putting the width directly on the contents of the div fixes FF's problems, that *could* make the extra markup <div> unnecessary.

the main reason (apart from FF's need) for the extra nested div was that it means you can then margin/pad internal elements without worrying about width settings/box model problems on individual internal elements.

It is weird that it puts the <p> and <ul> side by side hmmm there's more to this inline box than meets the eye hehe.. however the nested div does also take care of this.

I know Opera also understands the child selector, but I can't recall if it auto-encloses like IE...?

If you put a <ul> in there (with no adjustment to padding and margins on it) and use your child selector.
IE copes, it's not seeing the child selector anyway.
FF displays side by side - why?
Opera overflows the div ~ the div.box remains 150px but the list also remains 150px which along with it's indent and bullet makes it wider so it overflows the containing div. (Opera does not "auto enclose" except vertically when floats are involved afaik)

any word on which (if any) of these methods IE/Mac might like?

the nested div seems to be the best approach... so far anyway..

Suzy

createErrorMsg

9:50 pm on Mar 10, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



there's more to this inline box than meets the eye

Indeed! :)

The side-by-side thing is not limited to a list. It occurs whenever I place more than one block level element inside of .box. It doesn't seem to matter how the elements get a width (through the child selector or directly on the element), and aside from Moz/FF displaying it all in a line right out of box as you describe, it doesn't seem to matter whether it has a width or not. Without the extra containing <div>, the block level content of the .box displays side-by-side.

So it looks like with the .box set to -moz-inline-box, multiple block level children line up horizontally, not vertically.

This doesn't happen with the nested <div> because that div becomes the only block level child of .box. If you duplicate that div (with enough content in it for it to matter) so that there are two nested divs in .box, it lines those two divs up horizontally.

So the nested div is, as you said from the start, necessary for Moz/FF.

cEM