2

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>
Martin
  • 2,606
  • 4
  • 24
  • 38
  • 1
    some code please. We understand code better than story – Satpal Feb 03 '14 at 17:10
  • display:flex for the win – codeaddict Feb 03 '14 at 17:10
  • 1
    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 Feb 03 '14 at 17:11
  • 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](http://coding.smashingmagazine.com/2013/08/09/absolute-horizontal-vertical-centering-css/) 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 Feb 03 '14 at 17:13
  • here is an old test back from 2006 not using javascript and wich worked in IE55 & 6 http://gcyrillus.free.fr/essai/v-align-midlle-block-tous.html it involves inline-block and layout (FF 1 could understand display table not IE6 :) http://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 Feb 03 '14 at 17:35
  • You may want to use an example with unknown widths and heights (or percentages). This example can be centered using margins or with absolute positioning and left/top. – brouxhaha Feb 03 '14 at 17:35
  • There are like 4 different ways to solve my problem. 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? – Martin Feb 03 '14 at 17:56

5 Answers5

2

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

Community
  • 1
  • 1
Hashem Qolami
  • 97,268
  • 26
  • 150
  • 164
0

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%);
}
brouxhaha
  • 4,003
  • 1
  • 19
  • 22
0

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.

Pointy
  • 405,095
  • 59
  • 585
  • 614
0

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/

jmoody1988
  • 108
  • 4
  • If you read my question, I am asking why won't the text become centered when I use margin-top:auto; and margin-bottom:auto; and why does such a simple task have to be so extremely hard to solve. – Martin Feb 03 '14 at 18:07
-1

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;
}
Staff
  • 853
  • 1
  • 7
  • 10
  • Posting code alone won't help anyone understand your answer. Please explain what part of your code is the answer – aaron-bond Feb 03 '14 at 17:16
  • I want to center using CSS, not tables. I know web-devs gets hurt when someone use tables for anything not intended to be table formatted. – Martin Feb 03 '14 at 17:28
  • My god ! display:table is not , it is only the defaut display of table, like list-item is for lis or block is for div, do not mix CSS and HTML ...
    – G-Cyrillus Feb 03 '14 at 17:44
  • The guy changed his comment right after I commented ;) – Martin Feb 03 '14 at 17:47