views:

100

answers:

5

For me, one of the most useful features of tables is that their width adjust to its content.

You can very easily do things like:

<table align=center style="border: 1px solid black">
<tr><td style="padding: 20px">
some text here
</table>

If the content of that box is wider, the box will be wider. Very intuitive and it works on ALL browsers, period.

You can achive something similar for normal block elements by using the float CSS property, i.e. their width adjust to its content. But the element will not be centered.

So, the question: How can you center a block element and make that element to adjust its width to its content in a cross-browser manner?

A: 

Use this CSS

#content {
  position: absolute;
  width: 150px;
  margin-left: -75px;
  left: 50%;
  border: 1px solid #000;
  text-align: center;
  padding: 20px;
}

and this html <div id="content"> some text here </div>

jcubic
You have to specify the width for this...
meder
+1  A: 

If your intend is to display just some text at the middle of the page, you can use something like this:

<div style="text-align:center;">
    <div style="background:red;display:inline;">
        Hello World!
    </div>
</div>

The first block will align contents to the middle. The second will fill the height equal to its contents, since display:inline will force the <div/> block to behavior like a <span/>, ie. adjust its width to content, and not to the remaining space.

Note this is limited to single line text only (like "some text here").

MainMa
"So, the question: How can you center a block element and ..."
melhosseiny
"... and make that element to adjust its width to its content in a cross-browser manner". What's wrong? In the sample code I provided, the width will be adjusted to its content (contrary to the solution you provided), and it is obviously a cross-browser solution (IE6 does not agree with me?).
MainMa
Ah yes, maybe you're right and he meant that. But for me, "make that element to adjust its width to its content" doesn't mean align text to the center of element. Aligning text never changes the width of the containing element.
melhosseiny
Not sure if my answer was clear. In my case, the width of a span is equal to the width of "Hello World!" text, and the span element is aligned to the center. It's nothing to do about the parent `<div/>`. So in my case, "element" is span, and "content" is innerHTML of span.
MainMa
But what element had its width adjusted? The span will still have the same width.
melhosseiny
@melhosseiny "what element had its width adjusted?": the span. The question was how to center an element and make that element to adjust its width to content. The *span* is centered, and the width of the *span* is adjusted to content.
MainMa
The question was how to center a block element (not just any element), and if you take a look at http://jsfiddle.net/qa6Bn/ you'll see why the width of the span remains the same.
melhosseiny
Ah, ok. Edited the answer. So now the *child block-level element* is centered, and the width of the *child block-level element* is adjusted to content. "the width of the span remains the same": that was expected, isn't it? Since the content is the same, the width remains the same.
MainMa
This solution doesn't work well on IE6. Borders on inline elements are not handled properly. Actually inline elements are not meant to have borders since they may wrap through several lines of text (inline elements are not boxes). Anyway, what's the point of using a `div` and then setting `display:inline` for that `div`? why not just using a `span`?
GetFree
@GetFree: "what's the point of using a div" - in the first version of my answer, I mistakenly used `<span/>`, then melhosseiny noticed that the question is about block elements. What's the problem in IE6? In IETester, borders are displayed correctly.
MainMa
@MainMa, what if I have two lines of text?
GetFree
@GetFree: ok, now I see what's the problem with my code.
MainMa
+2  A: 

Quoting CSS: The Definitive Guide by Eric Meyer

If both margins are set to auto, as shown in the code below, then they are set to equal lengths, thus centering the element within its parent:

p {width: 100px; margin-left: auto; margin-right: auto;}

Setting both margins to equal lengths is the correct way to center elements, as opposed to using text-align. (text-align applies only to the inline content of a block-level element, so setting an element to have a text-align of center shouldn't center it.)

In practice, only browsers released after February 1999 correctly handle auto margin centering, and not all of them get it completely right. Those that do not handle auto margins correctly behave in inconsistent ways, but the safest bet is to assume that outdated browsers will reset both margins to zero.

However,

One of the more pernicious bugs in IE/Win up through IE6 is that it actually does treat text-align: center as if it were the element, and centers elements as well as text. This does not happen in standards mode in IE6 and later, but it persists in IE5.x and earlier.

melhosseiny
Yes, `text-align` centers the text within the block but does not center the block within *its* container.
Stephen P
You reminded me that this is not the case for IE<6. Not that anybody is still using those. However, it should be mentioned for completeness sake.
melhosseiny
+1  A: 

The modern way is to specify display:table and the workaround for IE is having a parent element and text-align:center on a inline/inline-block:

<div id="for-ie">
<div id="el">whatup son</div>
</div>

<style>
#el { 
display:table;
margin:0 auto;
}

/* for IE, throw this in a CC */
#for-ie { text-align:center; }
#el { 
zoom:1;
display:inline;
}
</style>

Demo

Here's a quick tutorial I wrote on this subject: http://work.arounds.org/centering-block-level-element-variable-width/

I'll lengthen it when I'm not sleepy.

meder
What's the point of display:table, triggering hasLayout and display:inline?
melhosseiny
`table` shrinkwraps the element for modern browsers. the other two are just for IE.
meder
There's also a way to center floats which are shrinkwrapped, without specifying widths if the IE workaround isn't ideal.
meder
This solution is the only one working so far. The part `</el>` caused one of my eyebrows to raise though.
GetFree
oops, typo. fixed. I doubt there's any other cross-browser way without relying on js/table elements.
meder
@GetFree - so are you going to mark an answer yet?
meder
A: 

Good golly, miss Molly! These answers are really overcomplicated.

CSS:

div.centered {
 width:100%;
 margin:0 auto;
 text-align:center;
}

div.centered span {
 padding:20px;
 border:1px solid #000;
}

And then use this in your body:

<div class="centered"><span>Hello world!</span></div>
ExtraNoise
It doesn't work in IE6. Borders on inline elements like `span` are not handled properly.
GetFree
@ExtraNoise - `width:100%` doesn't cause the block level to shrinkwrap. My solution is pretty succinct minus the IE fix.
meder