Vertical centering of elements in HTML

Published 1/18/2015

Preface

The vertical alignment, in particular centering, of HTML elements is a classic example of something that seems simple but in practice is very complicated. A lot of web developers straggle with it, and not only young developers. For example, I found six frequent (i.e. very popular) questions in Stack Overflow community dealing with this problem:

vertical alignment of elements in a div (September, 2008)
Vertically align text next to an image? (January, 2009)
How to vertically align an image inside div (September, 2011)
How to align text vertically center in div with CSS? (January, 2012)
Is it possible to vertically align text within a div? (February, 2012)
How to align checkboxes and their labels consistently cross-browsers (July, 2014)

The reason for such a situation is there is no single and unified way to align HTML elements vertically, but there is one or two less or more good methods still not fully supported by all the browsers and platforms, plus some less or more ugly and tricky workarounds. Probably the most confusing is the fact that CSS provides a property so logically named 'vertical-align', but because of various reasons it may or may not work with a certain element in the certain circumstances.

A lot of forum posts, Q&A threads and blog articles were published about vertical alignment and centering; there even exists a site (quite pure, though) specially dedicated to this. So, why have I decided to contribute? Mainly, it's because the information becomes outdated very quickly in our crazy world, especially in the super crazy world of computer programming. Even the really good sources that where undoubtedly relevant two or three years ago are almost obsolete nowadays and thus something more fresh is required.

This article explains the various methods of HTML elements centering including the most contemporary of them, examines their advantages and disadvantages and shows how to use these methods in the most common situations.

Tricky centering methods

I call the following methods "tricky" because of some reasons. First of all, they are not obvious. Logically, when a developer wants to center an element inside its parent he looks for something named "align", "center" or similar. These methods, however, use the properties like 'line-height' or 'position' which are not naturally related to alignment, but can be used for it. Secondly, these methods are based on some assumptions that essentially limit the use of them in many situations. Finally, they require a fine tuning on the level of pixels and so poorly comply with the responsive design approach.

Align with CSS Caricature

Line height trick

The idea of this method is very simple. All we need to do is to set a line-height for the element containing the text to the same value as its height. By default the space above and below the text are equal, so the text will be vertically centered:

HTML
div classcenter-textHello World!div
 
CSS
.center-text {
  • width400px;
  • height120px;
  • font-size24px;
  • line-height120px;
  • text-aligncenter;
  • background-color#fafafa;
  • bordersolid 1px lightgray;
}

As you see, it works, but with a 'small' limitation: it works with only one line of text, otherwise it doesn't. To put it mildly, it's not a very powerful method.

Absolute in relative position trick

This method is based on "margin: auto" property which can be used to center an element in its parent. However, it requires the width and height of the child element to be explicitly set like it's done in the following example:

HTML
div classcnt-div
  • img srccat.jpg
div
 
CSS
.cnt-div {
  • positionrelative;
  • width400px;
  • height120px;
  • background-color#fafafa;
  • bordersolid 1px lightgray;
}
.cnt-div > img {
  • positionabsolute;
  • width64px;
  • height64px;
  • left0;
  • top0;
  • right0;
  • bottom0;
  • marginauto;
}

Here we relatively easily succeeded to center an image inside the div block. It can also be acceptable for fixed width dialogs, for example, but what about a dynamic content we don't know the size of in advance?

Tricking with padding and margins

Of course, we can tune the positions of HTML elements by playing with padding and margins and there are a lot of recommendations on how to use them for centering. However, like the previous trick, this approach is good only for a static content and very problematic for a dynamic one. Moreover, too much exact sizes in pixels may cause serious problems with responsive design since the "a pixel is not a pixel" on many mobile devices.

Now let's have a look at two more universal and reliable methods.

Centering using CSS display table

Welcome to old bad time of HTML4 when the primary method of page layout was the use of tables! One thing worked well then: the vertical alignment. When the world finally made a long-awaited switch to HTML5 and started to use better layout methods, suddenly it was found that this functionality is missed. Nevertheless, nothing prevents us from using of tables without tables! Let me introduce to you the three CSS display property values: table, table-row and table-cell. Now practically any HTML element can behave like a table, row or cell, correspondingly.

In fact, table layout simulation in HTML5 and CSS3 is even better than the original table layout. First of all, you don't necessarily need to stick to the full table structure where tables contain rows and rows contain cells. You may use rows if you wish to, but you can also put 'table cells' directly inside the 'table'. Table, however, is required.

Secondly, while the rows of real tables only allow the vertical alignment and cells only allow the horizontal, the 'display: table-cell' allows both.

So, to center a content of the div element we can display it as 'table' and wrap the content in one additional element, for example span, displayed as 'table-cell'.

HTML
div classtbl-div
  • spanIt's no problem to centerbrmultiple lines of textspan
div
 
div classtbl-div
  • spanimg srccat.pngspan
div
 
CSS
.tbl-div {
  • displaytable;
  • width400px;
  • height120px;
  • background-color#ffe6cc;
  • bordersolid 1px lightgray;
}
.tbl-div > span {
  • displaytable-cell;
  • text-aligncenter;
  • vertical-alignmiddle;
}

The advantages of this method in comparison with the tricks described below are obvious. It's straightforward, universal and can be used with any containing and contained element types. You don't need to know the content beforehand; you don't need to deal with exact sizes and so on.

However, this method also has some disadvantages. Firstly, it requires the insertion of additional elements into the DOM structure. As we'll see later, in certain situations it may cause a considerable growth of the code size. Secondly, on the conceptual level we stay in the outdated paradigm of table-based layout and it's not that awesome.

Centering using Flexible Box Layout model

While the table-based method of alignment described above came from the past, the flexible boxes method definitely looks up to the future. Being first invented in 2009, CSS Flexible Box Layout model officially is still in drafts, but the modern browsers have already provided at least the basic level of support for it. I warmly recommend you learn more about flexible layout, but here we'll concentrate on our purpose.

The flexible boxes model provides a new terminology to properly describe itself and in particular brings the new sense to the terms 'alignment' and 'justification'. The 'justify-content' property defines how the items are laid out along the main axis and 'align-items' property defines how the items are laid out along the cross axis. What does it mean?

The main and cross axis's depend on the 'flex-direction' property value which can be 'row' (by default), 'reverse-row', 'column' or 'reverse-column'. In the first two cases the main axis is horizontal and the cross axis is vertical; and vice versa, in the second two cases the main axis is vertical and the cross axis is horizontal… it sounds complicated enough, doesn't it?

Don't worry! After deep learning of the flexible model, if you haven't learnt it yet, you will be familiar will all these notions. In the meantime, to use flexible boxes for centering elements only, you can use a simple mnemonic rule: justify horizontally, align vertically.

Well, the explanation probably was a little bit complicated, but the usage is very simple:

HTML
div classflex-div
  • It's no problem to centerbrmultiple lines of text
div
 
div classflex-divimg srccat.pngdiv
 
CSS
.flex-div {
  • displayflex;
  • width400px;
  • height120px;
  • justify-contentcenter;
  • align-itemscenter;
  • background-color#f0fff0;
  • bordersolid 1px lightgray;
}

This was even more simple and elegant than the table based alignment described before. Very short and clean code, no additional elements and even more accurate results. So, why won't we start to use this method always and forget about all its predecessors? The answer is simple: the compatibility.

The browsers compatibility issue

Accordantly to the information of 'Can I Use' site the CSS display table is fully supported by all the less or more modern browsers on all the platforms. The support for flex boxing model, however, is less complete. Internet Explorer 10 only provides a partial support and requires the vendor prefix; Safari requires the vendor prefix as well; and finally, Opera Mini doesn't support it yet.

Taking in account these compatibility issues and one's target auditory every developer can decide when to use the flex boxes anyway and when keep using the older table based layout until the flexible model specification will be finally released.

The most common centering cases

Below I'll show how to use both table-based and flexible-based methods in some common cases. For simplicity I'll omit the vendor-specific prefixes, but you should take care of them in your real code.

Textbox with wrapped image centering

In this sample we'll center a box with some text and image wrapped by it. The box is displayed as inline-block with fixed width. To make it more vivid let's decorate it with a different background color, border and shadow. To make the image wrapped by the text we'll float it to the left side and add a small padding on its right side:

CSS
.wrap-cnt {
  • displayinline-block;
  • width220px;
  • font-size16px;
  • text-alignjustify;
  • padding16px;
  • background-color#d7ffff;
  • displaysolid 1px gray;
  • box-shadow2px 2px 8px #c0c0c0;
}
.wrap-cnt img {
  • floatleft;
  • padding-right10px;
}

To center this box inside the external element, for example div, using the method of table layout we apply the same techniques as before: display the container as a table plus an additional span displayed as a table-cell inside:

HTML
div classwrap-tbl
  • div
    • div classwrap-cnt
      • img srcdog.pngThis content with image and text is an example of perfect centering of content inside its holder, both vertically and horizontally.
    • div
  • div
div
 
CSS
.wrap-tbl {
  • displaytable;
  • width400px;
  • height220px;
  • background-color#ffe6cc;
  • bordersolid 1px lightgray;
}
.wrap-tbl > .span {
  • displaytable-cell;
  • text-aligncenter;
  • vertical-alignmiddle;
}

To center it using flexible boxing model all we need is to display the container as flex and set the 'justify-content' and 'align-items' properties to 'center' as we have already made in the previous sample:

HTML
div classwrap-flex
  • div classwrap-cnt
    • img srcdog.pngThis content with image and text is an example of perfect centering of content inside its holder, both vertically and horizontally.
  • div
div
 
CSS
.wrap-flex {
  • displayflex;
  • width400px;
  • height220px;
  • justify-contentcenter;
  • align-itemscenter;
  • background-color#f0fff0;
  • bordersolid 1px lightgray;
}

Button with icon and text centering

In the previous example we did regard the centered block content as a single object, but in order to make a beautiful button with an icon and text they should be properly aligned relatively to one another. To meet this goal using the table based layout we have to put them in two separate cells. Therefore, our HTML will look as the following:

HTML
a href# classtbl-btn
  • spanimg srcsave.pngspan
  • spanSave everything!span
a

In CSS we'll make a class for our button and set its 'display' property to 'table'. Then we add the classes for the cells and the icon image. Pay attention that the image has to have a property 'float: left'!

CSS
.tbl-btn {
  • displaytable;
  • colorblack;
  • text-decorationnone;
  • padding12px 24px 12px 24px;
  • background-color#ffe6cc;
  • bordersolid 1px lightgray;
  • border-radius4px;
}
.tbl-btn span {
  • displaytable-cell;
  • vertical-alignmiddle;
}
.tbl-btn img {
  • floatleft;
  • margin-right6px;
}

Again, implementing the same task using flexible box is simpler. Both icon and text can be placed directly inside the button and no floating is necessary because the flexible model centering is smart enough to achieve a fine result. Pay attention that since the button doesn't have an explicit height the 'display' property should be set to 'inline-flex' value.

HTML
a href# classflex-btn
  • img srcsave.pngSave everything!
a
 
CSS
.flex-btn {
  • displayinline-flex;
  • align-itemscenter;
  • colorblack;
  • text-decorationnone;
  • padding12px 24px 12px 24px;
  • background-color#f0fff0;
  • bordersolid 1px lightgray;
  • border-radius4px;
}
.flex-btn img {
  • margin-right6px;
}

Menu with icon and text centering

The other common case is a menu which in HTML5 is usually composed on the base of unordered list. In the following sample we'll create a vertical menu with text and icons. Using the table based layout we should center the menu items in the same way as we centered the button in the previous sample, i.e. place the icons and the labels in separate cells:

HTML
ul classvmenu-tbl
  • li
    • spanimg srcfacebook.pngspan
    • spanFacebookspan
  • li
  • li
    • spanimg srcgoogleplus.pngspan
    • spanGoogle+span
  • li
  • li
    • spanimg srctwitter.pngspan
    • spanTwitterspan
  • li
  • li
    • spanimg srcreddit.pngspan
    • spanRedditspan
  • li
ul
 
CSS
.vmenu-tbl {
  • list-stylenone;
  • padding-left0;
  • font-size15px;
}
.vmenu-tbl li {
  • displaytable;
  • width100%;
  • margin0 0 2px 0;
  • padding5px 0 6px 8px;
  • background-color#ffe6cc;
  • bordersolid 1px lightgray;
}
.vmenu-tbl span {
  • displaytable-cell;
  • text-alignleft;
  • vertical-alignmiddle;
}
.vmenu-tbl span:first-child {
  • width1px;
}
.vmenu-tbl img {
  • floatleft;
  • margin-right6px;
}

With the flexible boxes model, as before, we can write more clean and compact code:

HTML
ul classvmenu-tbl
  • liimg srcfacebook.pngFacebookli
  • liimg src'googleplus.pngGoogle+li
  • liimg src'twitter.pngTwitterli
  • liimg src'reddit.pngRedditli
ul
 
CSS
.vmenu-flex {
  • list-stylenone;
  • padding-left0;
  • font-size15px;
}
.vmenu-flex li {
  • displayflex;
  • align-itemscenter;
  • padding5px 8px 6px 8px;
  • margin-bottom2px;
  • background-color#f0fff0;
  • bordersolid 1px lightgray;
}

To avoid the congestion of the article by too much code blocks I won't provide a sample of the horizontal menu which is the same as the vertical menu from the centering point of view.

Input controls with text labels centering

The last common case of centering I'd like to cover in this article is the centering of the text labels with the input controls like checkboxes, radio buttons, text boxes, etc. In general, it doesn't matter what to center, so a checkbox or a radio button do not differ from an icon. The two samples below which demonstrate this fact don't require more explanations.

Using the table layout:

HTML
div classchkbxs-group-tbl
  • div classchkbxs-tbl
    • spaninput typecheckboxspan
    • spanOption #1span
  • div
  • div classchkbxs-tbl
    • spaninput typecheckboxspan
    • spanOption #2span
  • div
  • div classchkbxs-tbl
    • spaninput typecheckboxspan
    • spanOption #3span
  • div
div
 
CSS
.chkbxs-group-tbl {
  • displayinline-block;
  • padding16px 32px 16px 24px;
  • background-color#ffe6cc;
  • bordersolid 1px lightgray;
  • border-radius3px;
}
.chkbxs-tbl {
  • displaytable;
  • font-size16px;
  • padding0 0 4px 0;
}
.chkbxs-tbl > span {
  • displaytable-cell;
  • vertical-alignmiddle;
}
.chkbxs-tbl > span:last-child {
  • padding-left6px;
}

Using the flexible boxes:

HTML
div classchkbxs-group-flex
  • div classchkbxs-flex
    • input typecheckboxspanOption #1span
  • div
  • div classchkbxs-flex
    • input typecheckboxspanOption #2span
  • div
  • div classchkbxs-flex
    • input typecheckboxspanOption #3span
  • div
div
 
CSS
.chkbxs-group-flex {
  • displayinline-block;
  • padding16px 32px 16px 24px;
  • background-color#f0fff0;
  • bordersolid 1px lightgray;
  • border-radius3px;
}
.chkbxs-flex {
  • displayflex;
  • align-itemscenter;
  • font-size16px;
  • padding0 0 4px 0;
}
.chkbxs-flex > span {
  • padding-left6px;
}

Conclusion

Therefore, there are two good universal methods of the HTML elements centering: the CSS table based layout and the flexible boxes model. The first is more reliable from the compatibility point of view, while the second is simpler, more accurate and allows the writing of more compact code.

The code samples used in this article are available at CodePen and you are welcomed to play with it.

Enjoyed this Article?
Recommend it to friends and colleagues!

7 Reader Comments