35

I am making a website and I'm trying to vertically center:

 position: absolute;
 width:1200px;
 height:600px;
 top: 50%;
 left: 50%;
 margin-left: -600px;

and my HTML is a single div

Fahim Parkar
  • 30,974
  • 45
  • 160
  • 276
swenflea
  • 562
  • 1
  • 5
  • 14
  • 1
    Doing `left: 50%;` and then `margin-left: -600px;` doesn't make much sense, since you're just canceling the one out with the other. – Jared Farrish Mar 19 '12 at 05:55
  • swenflea: I edited my question with information on the parent element's `position` effect. – Jared Farrish Mar 19 '12 at 06:19
  • Actually, can you be more specific with the Question? Do you want your DIV to be at the Center of the Page. I mean exact center....? – Vijay Sarin Mar 19 '12 at 06:30
  • @JaredFarrish It keeps the div exactly in the middel, however, I prefer to use width:calc(50% - 600px) – Maarten Wolfsen Sep 20 '16 at 08:38
  • 3
    @Swenflea, have you managed to fix this in the last seven years? If so, were any of the provided answers any good? If not, could you post your solution please? – sanepete Nov 28 '19 at 16:48

7 Answers7

58

Using Position - Static height needed

i{
  -webkit-transform: translate(-50%,-50%);
  transform: translate(-50%,-50%);
  position: absolute;
  top: 50%;
  left: 50%;
}
<i>center</i>

Edit: Using Flex (2021-10-19)

i {
  display: flex;
  align-items: center; /* vertical centering if flex-direction: row */
  justify-content: center; /* horizontal centering if flex-direction: row */

  /* extra styles */
  background-color: limeGreen;
  min-height: 160px;
}
<i>center</i>
enter code here
w3debugger
  • 2,097
  • 19
  • 23
  • 1
    this is the best solution IMO. – Kevin Jan 06 '17 at 19:40
  • 1
    thank you! I have been looking for this for forever! – Michael Mar 04 '17 at 04:15
  • 1
    This is not going to work if your parent has no static height, unless you have `height: 100%;` on both your html and body. You can check my answer bellow if you need more info. Also, you don't really need position absolute on some situations. This can work wit `position: relative;` for those worried in opting for this solution that need to it to keep positioning relationship with other elements. Although, a position value other than `position: static;` is required to for the `top` and `left` to work. (or even `bottom`, `right`, or`z-index`) – Jomar Sevillejo Oct 29 '17 at 00:24
  • @JomarSevillejo That's another technique. I just gave the answer by telling his current code. There can be `flexbox`/`table-cell`/`line-height`/ or anything else but why we're trying to let this guy rewrite his code? :) – w3debugger Oct 29 '17 at 12:30
  • @w3debugger I am not making the person change his answer. Please don't take it as offense. I simply warned everyone about how this method you showed, requires a static height if you use this with pposition: relative; on parent. http://prntscr.com/h3pbpf Most of the time we use `position:relative;` on parent to control absolute elements. and FYI the question is "WHY TOP:50%; IS NOT WORKING" so what's wrong with answering "YOU NEED A HEIGHT IN YOUR PARENT"? – Jomar Sevillejo Oct 30 '17 at 01:52
  • @JomarSevillejo I would never like your comment if I feel that offensive :) but sorry if that looks offensive as I'm not good in English. – w3debugger Oct 30 '17 at 08:30
33

To answer your question why top: 50% is not working, when you use property top on an element, the parent of that element needs to have a static height set in place. This should be in px or a unit other than percent. If you really need to use percent in your parent as well, then you can move on to the next parent (which is the parent of that parent) and have that one a fixed static height.

To vertically centering anything. I prefer to use this method

The use of CSS transform since you don't have to know what the width of height your element has.

position: relative;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);

Don't forget to add browser/vendor prefixes.

You can refer here for vendor prefixes.


If you don't know the height of your parent. You have two options:

  1. Using JavaScript take the natural height of the parent element and then set the height property of that parent element to the value you just took. You can use this method when the height of the parent element is caused by another child element that is sibling to the element you are centering.

$('.parent').height( $(this).height() );
.parent {
  /* Unkown height */
}

.child {
  /* Create columns */
  width: 50%;
  float: left;
}

.child-1 {
  position: relative;
  top: 50%;
  text-align: center;
  -webkit-transform: translateY(-50%);
  -moz-transform: translateY(-50%);
  -ms-transform: translateY(-50%);
  -o-transform: translateY(-50%);
  transform: translateY(-50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<!-- Example Start -->
<div class="parent">
  <div class="child child-1">
    Lorem ipsum
  </div>  
  <div class="child child-2">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </div>
</div>

Tip: If you are taking responsive into concern, just set height again in JavaScript on browser resize. You can get the new natural height by setting height to auto in JavaScript and do the process again.

  1. You can scratch the ideas above and use centering with display: table instead. CSS-Tricks has a very good example here.
TylerH
  • 20,799
  • 66
  • 75
  • 101
Jomar Sevillejo
  • 1,648
  • 2
  • 21
  • 33
  • 3
    "when you us property top on an element, the parent of that element needs to have a static height set" -- This was the answer to the question. Solved my issue in safari. – codescribblr Mar 17 '17 at 17:05
  • 2
    RE: "the parent of that element needs to have a static height set." Note 1: HTML and body can both be considered parents if there is no parent div. Note 2: A % will work too. For example amp.css contains the line: html,body{height: auto !important;} This can cause ads to be decapitated when you roll your own remote.html/frame.max.amp.html unless you add this css therein: html,body{height:100% !important;} That will allow the top:50% to work. – Brian Layman Mar 21 '17 at 23:31
15

The CSS property top works exactly as left. It pushes the div from that direction. When you write top:50%, the div will be pushed down 50% from the top. You want it to be centered vertically, so you need to counter this by pulling it back up. This can be done using margin-top: -300px just like you used margin-left: -600px to pull it left.

position: absolute;
width: 1200px;
height: 600px;
top: 50%;
margin-top: -300px;
left: 50%;
margin-left: -600px;
kba
  • 19,333
  • 5
  • 62
  • 89
  • 1
    This works for fixed height elements. For variable heights, use [this](http://stackoverflow.com/a/29232492/3389737). – Luke Aug 30 '16 at 16:45
4

top:50%; works fine, but wont "center" the item, it will place it's top edge 50% of the page's height from the top. Similarly to how you have margin-left:-600px; you should also add margin-top:-300px;

lukiffer
  • 11,025
  • 8
  • 46
  • 70
  • 1
    Sorry that doesn't work... it just sticks it -300px from the top of the page... Do I need to have any styling on outer divs or inner divs? – swenflea Mar 19 '12 at 05:37
  • Are you experiencing this in a specific browser? So long as it's position:absolute, the styles on the containing elements shouldn't matter unless the selector you're using is more specific and is overriding the style you listed above. – lukiffer Mar 19 '12 at 05:47
3

You can use

calc(%50 - (items_height/2));

to center.

tolga
  • 2,462
  • 4
  • 31
  • 57
  • 1
    I would have added more context around that statement, but this is what I was about to suggest. – Tgwizman Jun 19 '19 at 20:10
  • 1
    Note, it should be 50% rather than %50. And don't forget to add "px" after the second value. The format should be something like `calc(50% - 5px);`. For example this won't work: `calc(50% - (10/2)px);` – infografnet Jul 24 '22 at 17:25
1

css "top" property gets correctly calculated based on the container element's height - effectively rendering the target element below the midline. What this means is the element needs to be pushed half-way up as explained in the linked question.

Unfortunately such a seemingly straightforward task cannot be accomplished by adjusting top margin etc. without using absolute pixel-based values (+1 for Kristian Antonsen's answer) - one would imagine setting margin-top to "-50%" would mean just that, but according to css spec, margin values even on the vertical axis are calculated as a percentage always relative to the width of the containing block

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Oleg
  • 24,465
  • 8
  • 61
  • 91
0

I believe this may somewhat mimic the answer Kristian gave, but here's my two cents, which includes using percentages and also demonstrates one inside another:

#parent {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 120px;
    height: 60px;
    margin: -60px 0 0 -30px;
    background: blue;
}
#center {
    position: absolute;
    width: 50%;
    height: 50%;
    top: 50%;
    left: 50%;
    margin: -12.5% 0 0 -25%;
    background: green;
}

http://jsfiddle.net/userdude/MYD27/

EDIT

Looking at it further, I think you might run into issues if you're trying to do this with an element not container within a positioned element. For instance:

Full View | Code View

I don't think works the way you intended. When I add position: relative (or alternatively position: absolute), it does work I think as you intended:

Full View | Code View

Jared Farrish
  • 48,585
  • 17
  • 95
  • 104
  • +1 for the explanation about the `position: relative` (or absolute) in the parent DIV. That is what made it work for me. – Alexis Wilke Jan 17 '14 at 02:50