2
votes

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>
5
some code please. We understand code better than storySatpal
display:flex for the wincodeaddict
vertical-align works for content inside a table-cell (td or display as ) or in between inline-boxe using their baseline as reference. display:table-cell works in IE8 and it makes things really easy :)G-Cyrillus
If it's just one line of text, you could set the line-height to be equal to the parent's width. Otherwise, you could just use an offset margin with absolute positioning (Click here for a blog post all about absolute vertical positioning). Or, like @GCyrillus suggests, make the parent display:table and it's children to display:table-cell;vertical-align:middle.Jack
here is an old test back from 2006 not using javascript and wich worked in IE55 & 6 gcyrillus.free.fr/essai/v-align-midlle-block-tous.html it involves inline-block and layout (FF 1 could understand display table not IE6 :) gcyrillus.free.fr/essai/v-align-midlle-block-tous.html ) The red element shows what's going on and can be nowdays a pseudo-element or not used if display:table method is chosen :)G-Cyrillus

5 Answers

2
votes

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

0
votes

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%);
}
0
votes

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.

0
votes

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/

-1
votes

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;
}