Martin
Martin

Reputation: 2785

Vertical center with CSS

I know there are many ways to center things with CSS. Centering anything horizontally is quite straight forward. However, if you are going to center anything vertically, it is a whole new story. I just want to know why we can't just say bottom-align:auto; top-align:auto; as we do when we want something centered horizontally? Why does something which seems as simple as centering something seem so hard when centering something horizontally is that simple? I know there are many ways, but let's just say you have an element of an unknown size you want to center inside another element of unknown size.

I have been sitting with this for almost two days without finding a good question on this answer, we have tons of different ways to center items horizontally, but why has not one single CSS standard come up with a way to center this vertically? Is it a bad thing to do? Does it make people cry or randomly go into labor? Does it melt down nuclear reactors?

We live in 2014. It seems unnecessary to have to use Javascript in order to do something as simple as to center something inside another element.

Edit: Code sample of what I mean: http://jsfiddle.net/VsakD/

CSS:

div.parentbox
{
    width:500px;
    height:500px;
    border-style:solid;
}

div.childbox
{
    width:300px;
    height:300px;   
    border-style:solid;
    margin-left:auto;
    margin-right:auto;
    margin-top:auto;
    margin-bottom:auto;
}

HTML:

<div class="parentbox">
    <div class="childbox">
        I shall be in the middle of parentbox regardless of its size!
    </div>
</div>

Upvotes: 2

Views: 845

Answers (5)

Hashem Qolami
Hashem Qolami

Reputation: 99494

Can someone please highlight exactly why I can't just say margin-top:auto; margin-bottom:auto; to vertical align, which would be logical to assume would work since you do margin-left:auto; margin:right:auto; to horizontally align?

According to Spec (10.6.2):

Inline replaced elements, block-level replaced elements in normal flow, 'inline-block' replaced elements in normal flow and floating replaced elements

If 'margin-top', or 'margin-bottom' are 'auto', their used value is 0.

That's why using top/bottom margin is this case, doesn't make a change.

By the way, in order to align a div element (with unknown dimensions) vertically inside a container, you could follow this approach:

.parentbox {        
    text-align: center; /* Align inline elements center horizontally */
    font: 0/0 a; /* <-- remove the gap between inline(-block) elements */
}

.parentbox:before {
    content: ' ';
    display: inline-block;
    vertical-align: middle;
    height: 100%;
}

.childbox {
    display: inline-block;
    vertical-align: middle;
    font: 1rem/1 Arial, sans-serif;  /* <-- Reset the font */
}

WORKING DEMO

Upvotes: 2

jmoody1988
jmoody1988

Reputation: 108

The best way I have achieved the technique you desire is by using table display rules.

<div class="parent-container'>
   <div class="child-container">
         This is vertically centered text!
   </div>
</div>

The trick is in the CSS

    .parent-container {
        display: table;
        width: 100%;
        height: 300px;
        background-color: #ff0000;
    }

    .child-container {
        display: table-cell;
        vertical-align: middle;
    }

By making the parent container display as a table, and the child display as the cell, it follows the same vertical alignment rules as a table, because that's what you're telling it to recognize itself as.

Here's my JS fiddle for reference. I put a fixed height to show the vertical alignment in action, but in reality, it will work with percentage heights or calculated heights from padding as well. http://jsfiddle.net/JTVeG/

Upvotes: 0

Staff
Staff

Reputation: 933

Author code with modifications I shall be in the middle of parentbox regardless of its size!

div.parentbox
{
    width:500px;
    height:500px;
    border-style:solid;
    display: table; //added this line
}

div.childbox
{
    width:300px;
    height:300px;   
    border-style:solid;
    margin-left:auto;
    margin-right:auto;
    margin-top:auto;
    margin-bottom:auto;
    display: table-cell; //added this line
    vertical-align: middle;
    text-align: center;
}

Upvotes: -1

Pointy
Pointy

Reputation: 413757

The display: table approach is one way, but it's also possible to take advantage of CSS transforms. Unlike many other CSS properties like "top", for which percentages are figured relative to the containing element, the CSS transforms apply percentages to the element itself. Thus, you can position an element 50% of the way down inside its container, and then transform it up by 50% of its own size:

.center-me {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
  margin-left: auto; margin-right: auto;
  width: 300px; /* or whatever */
}

<div class=center-me> Hello World! </div>

Thanks go to the great Dave Walsh. Here is a jsfiddle to demonstrate.

Upvotes: 0

brouxhaha
brouxhaha

Reputation: 4093

You can easily find the older techniques to do so, but there's a newer technique discussed here: http://zerosixthree.se/vertical-align-anything-with-just-3-lines-of-css/

It works in IE9+ and all other browsers. The benefit of using this is not having to know the height of an element or use absolute positioning. Multiple lines of text aren't affected by the line-height method.

.element {
    position: relative;
    top: 50%;
    transform: translateY(-50%);
}

Upvotes: 0

Related Questions