93

I have a div that will have this CSS:

#some_kind_of_popup
{
    position: fixed;
    top: 100px;
    min-height: 300px;
    width: 90%;
    max-width: 900px;
}

Now, how can i make this div centered? I can use margin-left: -450px; left: 50%; but this will only work when the screen is > 900 pixels. After that (when the window is < 900 pixels), it will no longer be centered.

I can of course do this with some kind of js, but is there a "more correct" of doing this with CSS?

Hemerson Varela
  • 24,034
  • 16
  • 68
  • 69
gubbfett
  • 2,157
  • 6
  • 32
  • 54
  • 4
    @Liam - I disagree, I think this question is an outright on its own. Those questions don't answer this one in regards to having a div of no fixed width centred. –  Jun 12 '13 at 15:33
  • What Joshua said, that is for centering a div in another. – gubbfett Jun 12 '13 at 15:34
  • 7
    @Liam - Further to that, you can't use a `margin: 0 auto` on a `position: fixed` div. Did you even read the question? –  Jun 12 '13 at 15:35
  • ^nope. i've tried that as well. :p – gubbfett Jun 12 '13 at 15:36
  • the point is @JoshuaM, everyone wants to do this. It's been discussed on meta before (http://meta.stackexchange.com/questions/116673/creating-an-faq-post-to-answer-the-css-question-how-do-i-center-something). There are hundreds of answers for this question already on SO and yet another does not contribute to the site – Liam Jun 12 '13 at 15:53
  • @Liam this question is a bit different from the ones you linked here. The technique used is similar but not the same because it is applied on a `fixed` positioned element. – laconbass Jun 12 '13 at 15:59
  • 3
    @JoshuaM Your assertion isn't 100% correct. See my answer. – laconbass Jun 12 '13 at 16:01
  • @laconbass I stand (mostly) corrected! –  Jun 12 '13 at 16:35

5 Answers5

237

You can center a fixed or absolute positioned element setting right and left to 0, and then margin-left & margin-right to auto as if you were centering a static positioned element.

#example {
    position: fixed;
    /* center the element */
    right: 0;
    left: 0;
    margin-right: auto;
    margin-left: auto;
    /* give it dimensions */
    min-height: 10em;
    width: 90%;
}

See this example working on this fiddle.

laconbass
  • 17,080
  • 8
  • 46
  • 54
  • 1
    Just to mention... It's not that unexpected, but it fails in IE7. It's positioned 0px from left here. It does how ever work perfect in IE 8. – gubbfett Jun 12 '13 at 16:28
  • This doesn't work when the width of the element is greater than the width of the screen.. would be nice to have it work in that situation. – andrewb Apr 17 '14 at 12:10
  • 1
    @andrewb you could apply an equally negative margin both on `right` and `left` of at least a `value >= witdth / 2`, as seen on http://jsfiddle.net/PvfFy/168/, but is non an elegant approach IMHO. I have tested it on chrome for fun, I don't know if it will work on the rest – laconbass May 28 '14 at 18:28
  • 5
    Outside the scope of the question, this depends on setting the element's width, so it's not great if you have dynamic content whose width is varying or unknown. Leaving centering aside, I'd normally do that with display: inline-block and no set width. Does anyone have a no-js solution for that case? – enigment Feb 18 '15 at 14:07
  • @enigment Are you asking for a solution to make a fixed or absolute positioned element "adapt" its width to its content width? – laconbass Feb 25 '15 at 02:07
  • Just because it works in one contrived example doesn't mean CSS isn't a broken and disgusting mess. – Alexander Kleinhans May 22 '15 at 17:15
  • Yes it does work! Just set the width of the div to a % value, but not a fixed pixel value. E.g. width: 95%. – S. F. Nov 24 '15 at 09:41
  • @SpYk3HH Maybe the question title leads to a misunderstanding due to the term "dynamic width". The OP asks with an example of a div with a % width set - which actually is "dynamic" because it adapts to the viewport with. What you are asking for could also be called "dynamic", as it adapts to the content size, so maybe the question title isn't enought descriptive. – laconbass Feb 04 '16 at 10:03
  • For anyone interested on clarification for the meaning of *dynamic width*, please visit [Terminology: Does the meaning of “dynamic width” have a consensus?](http://stackoverflow.com/questions/35198428/terminology-does-the-meaning-of-dynamic-width-have-a-consensus) – laconbass Feb 04 '16 at 10:25
  • The problem with ‘position: fixed’ is that then the window doesn’t scroll (at least not on Safari on Mac or iPhone). ‘Position: absolute’ is OK in this respect. – David Jul 04 '16 at 21:55
  • 4
    The question says **dynamic width**, that's the whole problem, you can't just ignore that. – Gil Epshtain Apr 11 '18 at 14:24
  • It's an old post but could you elaborate on "as if you were centering a `static` positioned element"? Simply setting the margins to `auto` does not center a static element, and properties like `left` and `right` don't apply to static elements. – theberzi Jan 31 '21 at 11:34
  • @theberzi any `static` positioned element will center when `left` and `right` **margins** are set to `auto` and has `with != auto`. You can't center an element which has full-with of its container – laconbass Feb 01 '21 at 10:36
  • Oh, the missing bit was that it needs to have an explicit `width`. Not all elements automatically fill the width of their parent (e.g. ``) so that maybe a given for divs but not in general. – theberzi Feb 01 '21 at 10:53
  • @theberzi I think `position` don't works on `inline` elements. Don't remember if it does within `inline-block` elements. You are welcome ;) – laconbass Feb 01 '21 at 15:14
60

Here's another method if you can safely use CSS3's transform property:

.fixed-horizontal-center
{
    position: fixed;
    top: 100px; /* or whatever top you need */
    left: 50%;
    width: auto;
    -webkit-transform: translateX(-50%);
    -moz-transform: translateX(-50%);
    -ms-transform: translateX(-50%);
    -o-transform: translateX(-50%);
    transform: translateX(-50%);
}

...or if you want both horizontal AND vertical centering:

.fixed-center
{
    position: fixed;
    top: 50%;
    left: 50%;
    width: auto;
    height: auto;
    -webkit-transform: translate(-50%,-50%);
    -moz-transform: translate(-50%,-50%);
    -ms-transform: translate(-50%,-50%);
    -o-transform: translate(-50%,-50%);
    transform: translate(-50%,-50%);
}
Community
  • 1
  • 1
Alan Bellows
  • 1,781
  • 1
  • 14
  • 21
  • 5
    As long as it's for a modern browser, this is the ***BEST*** solution on this answer! The only one that is like a *true* `float: center', in that you can click around wrapping element and not be stuck having to fish ways around it. Love this answer! – SpYk3HH Jul 07 '15 at 14:50
  • 1
    Careful, do not use translation in percentage to center text as it will be smoothed if the resulting value is a float. Ho boy, you don't want that, no you don't. – gnou Jul 19 '15 at 16:02
  • Using CSS transforms can cause smoothing to occur on more than just text; I'm getting funky borders as a result of the transformation. – Nathan K Dec 05 '16 at 02:22
  • 1
    Potential to contract early when changing screen size (depending on the size of the division), resulting in large boarders around the edge of the division. – Single Entity Apr 19 '17 at 09:17
9

This works regardless of the size of its contents

.centered {
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }

source: https://css-tricks.com/quick-css-trick-how-to-center-an-object-exactly-in-the-center/

GorvGoyl
  • 42,508
  • 29
  • 229
  • 225
Leonardo
  • 1,001
  • 1
  • 13
  • 15
  • 2
    beware: `transform: translate(-50%, -50%);` causes text to be blurry (at least on chrome) – Jiří Aug 09 '20 at 17:17
  • @Jiří not in my case – GorvGoyl Nov 14 '21 at 22:47
  • for me also not anymore, maybe it was a bug... but I remember clearly that the whole container became blurred after this, if only slightly... let's delete this discussion? – Jiří Nov 15 '21 at 16:28
8
<div id="container">
    <div id="some_kind_of_popup">
        center me
    </div>
</div>

You'd need to wrap it in a container. here's the css

#container{
    position: fixed;
    top: 100px;
    width: 100%;
    text-align: center;
}
#some_kind_of_popup{
    display:inline-block;
    width: 90%;
    max-width: 900px;  
    min-height: 300px;  
}
Mathew Berg
  • 28,625
  • 11
  • 69
  • 90
  • Ah, i like your thinking. The fixed div will only be a container for another div with the actual result? I'll try this one! – gubbfett Jun 12 '13 at 15:41
  • While I do like the intuitiveness of your answer I do not see how it would allow support of ie6/7. – Mathew Berg Jun 12 '13 at 18:37
  • 1
    @MathewBerg, good point about ie6/7. In that case your answer should work best. This is a little OT, but personally i think developers should'nt spend time fixing stuff for <= ie7. I think actually developers should block those browsers to force people and companies with old systems to upgrade. It is how ever hard to sell that idea to a paying customer! ;) – gubbfett Jun 13 '13 at 08:43
  • Yes, but unfortunately some companies require support for legacy browsers no matter how far into the future we get. Go ahead and accept either mine or laconbass' answer depending on your needs. – Mathew Berg Jun 13 '13 at 15:25
  • @MathewBerg I agree both with your last comment and the gubbfett one. If the client wants to support ie6/7 it must be done, and the solution you propose effectively does the job. – laconbass Jun 18 '13 at 13:43
  • 1
    this also doesn't work as you still can't click through "container" – SpYk3HH Jul 07 '15 at 14:47
1

This approach will not limit element's width when using margins in flexbox

top: 0; left: 0;
transform: translate(calc(50vw - 50%));

Also for centering it vertically

top: 0; left: 0;
transform: translate(calc(50vw - 50%), calc(50vh - 50%));
proseosoc
  • 1,168
  • 14
  • 23