28

I've seen a million questions about how to center a block element and there seem to be a couple popular ways to do it, but they all rely on fixed pixels widths. Then either margin:0 auto or with absolute/relative positioning and left:50%; margin-left:[-1/2 width]; etc. We all know this can't work if the element has a width set in %.

Is there really no way to do this in a way that is truly fluid? I'm talking about using % for width (not setting a dozen media queries with increasingly small fixed widths).

Beware: there are tons of solutions out there which use the buzz word "responsive" but don't answer my question (because they use fixed widths anyway). Here's an example.

Update: I almost forgot: how do you handle limiting the max-width of the centered element and still keep it in the center? See my comment under @smdrager's answer. Real-life example. I want a pop-up message or a light box effect containing a paragraph of text to appear centered in the window and the text to wrap fluidly depending on the width. But I don't want the text box to stretch out toooo far where the text would get difficult to read (imagine a 4ft screen with three paragraphs stretched out onto a single line of text). If you add a max-width to most approaches, the centered box will stop centering when the max-width is reached.

Community
  • 1
  • 1
emersonthis
  • 32,822
  • 59
  • 210
  • 375

6 Answers6

42

Centering both horizontally and vertically

Actually, having the height and width in percents makes centering it even easier. You just offset the left and top by half of the area not occupied by the div.

So if you height is 40%, 100% - 40% = 60%. So you want 30% above and below. Then top: 30% does the trick.

See the example here: http://dabblet.com/gist/5957545

Centering only horizontally

Use inline-block. The other answer here will not work for IE 8 and below, however. You must use a CSS hack or conditional styles for that. Here is the hack version:

See the example here: http://dabblet.com/gist/5957591

.inlineblock { 
    display: inline-block;
    zoom: 1;
    display*: inline; /* ie hack */
}

EDIT

By using media queries you can combine two techniques to achive the effect you want. The only complication is height. You use a nested div to switch between % width and

http://dabblet.com/gist/5957676

@media (max-width: 1000px) {
    .center{}
    .center-inner{left:25%;top:25%;position:absolute;width:50%;height:300px;background:#f0f;text-align:center;max-width:500px;max-height:500px;}
}
@media (min-width: 1000px) {
    .center{left:50%;top:25%;position:absolute;}
    .center-inner{width:500px;height:100%;margin-left:-250px;height:300px;background:#f0f;text-align:center;max-width:500px;max-height:500px;}
}
smdrager
  • 7,327
  • 6
  • 39
  • 49
  • Right! Yours works. But I forgot to mention one more problem: setting a max-width/height. This is where I always get stuck. For example, pretend the centered box is a pop-up with a paragraph of text. You want it in the middle of the screen but if someone is viewing on a 4ft wide screen, you don't want the box width to scale allllll the way up and turn into a single super-long line. Is there a way to handle that? – emersonthis Jul 09 '13 at 14:07
  • A popup and a page are different cases. in one case you set an height to 100% and the other a min-height on which content goes vertical-align. For the width, it is all up to your choice to define value of max-width. – G-Cyrillus Jul 09 '13 at 14:14
  • Edited to include your new spec :) – smdrager Jul 09 '13 at 14:17
  • Now we're talkin'!! Can you explain your IE hack from the original code (`display*...`). I see you removed it in the second iteration. – emersonthis Jul 09 '13 at 14:25
  • The EDIT version doesn't use the hack. Here is an explanation of how it works, though: http://stackoverflow.com/a/6545033/356550 – smdrager Jul 09 '13 at 14:30
  • The OP explicitly mentioned a solution without adaptive solutions and for fluid results. Also when displaying an absolute div inline block its parent would have to have text-align:center; So that's out. – Ben Racicot Jan 02 '15 at 20:26
  • @BenRacicot where does he explicitly say no adaptive solutions? – smdrager Jun 08 '15 at 20:46
  • His first sentence, "but they all rely on fixed pixels widths." – Ben Racicot Jun 08 '15 at 21:11
20

From Chris Coyier's article on centering percentage width elements:

Instead of using negative margins, you use negative translate() transforms.

.center {
  position: absolute;
  left: 50%;
  top: 50%;

  /*
  Nope =(
  margin-left: -25%;
  margin-top: -25%;
  */

  /* 
  Yep!
  */
  transform: translate(-50%, -50%);

  /*
  Not even necessary really. 
  e.g. Height could be left out!
  */
  width: 40%;
  height: 50%;
}

Codepen

Brian Phillips
  • 4,302
  • 2
  • 25
  • 40
  • 1
    This is a cool idea. But isn't browser support for css transformations still very thin? I didn't stipulate browser support, but my sense is that this would almost always require a js fallback for any production project. No? – emersonthis Jul 09 '13 at 14:18
  • @SDP Any user still using Windows XP and IE 8 can't view that. Any user with ie 10-11, chrome, firefox, safari and any mobile browser based on chrome, firefox or ie 10-11 will see it, so it shouldn't be a problem. There was a downside however in using translate, but nothing incredibly bad, the problem is that I don't remember what was that now (nothing about performance or compatibility). The fact that the question was asked 1 year ago requires also updating the answer which probably makes this the correct one. – Francesco Belladonna Jul 29 '14 at 23:03
  • It should be noted that `transform` is rather impractical to use for positioning. One reason being that when you want to animate the target element using a keyframed animation that includes transforms, they will overwrite your centering forcing you to rewrite the animations. That's a generic issue with how poor CSS transforms and keyframe animations are, not specific to just this example. – zrooda Apr 27 '15 at 18:24
12

I think you can use display: inline-block on the element you want to center and set text-align: center; on its parent. This definitely center the div on all screen sizes.

Here you can see a fiddle: http://jsfiddle.net/PwC4T/2/ I add the code here for completeness.

HTML

<div id="container">
    <div id="main">
        <div id="somebackground">
            Hi
        </div>
    </div>
</div>

CSS

#container
{
    text-align: center;
}
#main
{
    display: inline-block;
}
#somebackground
{
    text-align: left;
    background-color: red;
}

For vertical centering, I "dropped" support for some older browsers in favour of display: table;, which absolutely reduce code, see this fiddle: http://jsfiddle.net/jFAjY/1/

Here is the code (again) for completeness:

HTML

<body>
    <div id="table-container">
        <div id="container">
            <div id="main">
                <div id="somebackground">
                    Hi
                </div>
            </div>
        </div>
    </div>
</body>

CSS

body, html
{
    height: 100%;
}
#table-container
{
    display:    table;
    text-align: center;
    width:      100%;
    height:     100%;
}
#container
{
    display:        table-cell;
    vertical-align: middle;
}
#main
{
    display: inline-block;
}
#somebackground
{
    text-align:       left;
    background-color: red;
}

The advantage of this approach? You don't have to deal with any percantage, it also handles correctly the <video> tag (html5), which has two different sizes (one during load, one after load, you can't fetch the tag size 'till video is loaded).

The downside is that it drops support for some older browser (I think IE8 won't handle this correctly)

Francesco Belladonna
  • 11,361
  • 12
  • 77
  • 147
  • Cool idea. For completeness, can you provide a jsfiddle or some code? – emersonthis Jul 09 '13 at 14:01
  • @Emerson: Updated for vertical centering too, you can also see two fiddles (one with horizontal centering only, one for vertical and horizontal centering). – Francesco Belladonna Jul 09 '13 at 14:57
  • @Emerson: Next step will be flexbox: http://weblog.bocoup.com/dive-into-flexbox/ but this is not supported at the moment. – Francesco Belladonna Jul 09 '13 at 15:10
  • Thanks so much for this answer, I always forget how to quickly center a div without giving absolute width, but with this method I can easily remember [text-align: center div with child div display:inline-block]. – Matt Jul 29 '14 at 22:52
  • This is great for elements with dynamic widths thank you – random-forest-cat Jan 07 '17 at 19:56
  • How do I get this to play nicely with a button that is inside the `somebackground` div? It shows up on a new line across browsers and Safari ignores the fact that I told it to go be centered. – cjm Mar 11 '17 at 04:58
2

EDIT :
http://codepen.io/gcyrillus/pen/daCyu So for a popup, you have to use position:fixed , display:table property and max-width with em or rem values :)
with this CSS basis :

#popup {
  position:fixed;
  width:100%;
  height:100%;
  display:table;
  pointer-events:none;
}
#popup > div {
  display:table-cell;
  vertical-align:middle;
}
#popup p {
  width:80%;
  max-width:20em;
  margin:auto;
  pointer-events:auto;
}
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
0

Something like this could be it?

HTML

 <div class="random">
        SOMETHING
 </div>

CSS

body{

    text-align: center;
}

.random{

    width: 60%;
    margin: auto;
    background-color: yellow;
    display:block;

}

DEMO: http://jsfiddle.net/t5Pp2/2/

Edit: adding display:block doesn't ruin the thing, so...

You can also set the margin to: margin: 0 auto 0 auto; just to be sure it centers only this way not from the top too.

Ms. Nobody
  • 1,219
  • 3
  • 14
  • 34
  • why there is need for body css, it should not depend on body css as question is to center the element in a div, so it should be independent from body css – lal rishav Mar 23 '20 at 17:54
0

This might sound really simplistic...

But this will center the div inside the div, exactly in the center in relation to left and right margin or parent container, but you can adjust percentage symmetrically on left and right.

margin-right: 10%;
margin-left: 10%;

Then you can adjust % to make it as wide as you want it.

Bruno Vincent
  • 525
  • 1
  • 5
  • 18