Why doesn't vertical-align: middle work?

Why doesn’t vertical-align: middle work? How to vertically-centre elements in HTML and CSS

If you are new to working with CSS, you may find that the language comes with its fair share of quirks that can be frustrating, such as the text-align attribute not always working at horizontally-aligning your content.

In a similar way to text-align, the vertical-align attribute doesn’t always work at aligning your content vertically. Take the following HTML code for example:

<div style="width:100%;height:140px;background:#ddd;text-align:center;vertical-align:middle;">
	<img src="http://placekitten.com/75/75"/>
</div>

Even with the vertical-align:middle style assigned to it, the image doesn’t align itself vertically! What’s going on? Here’s a quick breakdown of how to do it, with lots of examples, without having to do too much reading (great for if you’re rushing out a school assignment).

  1. Introduction
  2. Using tables for alignment
    1. Using vertical-align on table elements
    2. Using display: table to emulate table behaviour
  3. Using CSS grids for alignment
    1. Using align-items
    2. Using align-self
  4. Using CSS flexbox for alignment
    1. Using align-items
    2. Using margin: auto
  5. Using Bootstrap 4 and up
  6. Conclusion

1. Introduction

The reason the example listed above does not work is because vertical-align is not primarily-designed to align elements vertically in a container, like text-align does for horizontal alignment. It is designed to control the vertical alignment of inline elements relative to each other (I wrote an article about this, if you want to learn more).

There are, however, ways that you can get vertical-align to switch up its behaviour, and position elements in your container. This article explores that, if you continue reading, you will become a master at doing this:

“Meow! I am now vertically-aligned!”

2. Using tables for alignment

Tables are one of the oldest elements in HTML, and they also have some quirks that are unique to them. One of these quirks is that the vertical-align attribute, which, when applied to the elements in a table, aligns content with reference to the height of the entire cell.

a. Using vertical-align on table elements

<table style="width:100px;min-height:300px;background:#eee;width:100%;" border="1" cellspacing="0" cellpadding="0">
  <tr>
    <td style="vertical-align: top;"><img src="http://placekitten.com/50/50" alt="Kitten"/></td>
    <td style="vertical-align: middle;"><img src="http://placekitten.com/52/50" alt="Kitten"/></td>
    <td style="vertical-align: bottom;"><img src="http://placekitten.com/54/50" alt="Kitten"/></td>
  </tr>
</table>
Kitten Kitten Kitten

Note that you can also apply vertical-align on parent elements, and it will be inherited by the children:

<table style="width:100px;min-height:300px;background:#eee;width:100%;vertical-align:middle;" border="1" cellspacing="0" cellpadding="0">
  <tr>
    <td><img src="http://placekitten.com/50/50" alt="Kitten"/></td>
    <td><img src="http://placekitten.com/52/50" alt="Kitten"/></td>
    <td><img src="http://placekitten.com/54/50" alt="Kitten"/></td>
  </tr>
</table>
Kitten Kitten Kitten

Article continues after the advertisement:


b. Using display:table to emulate table behaviour

However, sometimes, we might not want to use tables to create our web content, as they are designed to display tabular data, and can be very difficult to make responsive. In such cases, we can use display:table in combination with display:table-cell, so that the element with display:table-cell will display vertical-align like a table element.

Note, however, that you will need at least 2 elements:

  1. An element with display:table, and;
  2. An element with display:table-cell as a direct child of the above element.

The element (which can be almost of any type) with display:table-cell attribute will then be able to be vertically-aligned. Below is an example:

<section style="width:100%; min-height:130px;background:#eee;display:table;">
  <figure style="display:table-cell;vertical-align:middle;"><img src="http://placekitten.com/61/62" alt="Kitten"/></figure>
</section>
Kitten

Note that display:table-cell only works on container elements. You cannot place it directly onto an <img> tag and vertical-align it, like so: <img style="display:table-cell;vertical-align:middle;">.

If you need to horizontally-align the element too, you can still use text-align:center on the table cell:

<section style="width:100%; min-height:130px;background:#eee;display:table;">
  <figure style="display:table-cell;vertical-align:middle;text-align:center;"><img src="http://placekitten.com/61/62" alt="Kitten"/></figure>
</section>
Kitten

3. Using CSS grids for alignment

A relatively-new feature in web development, CSS grids were proposed all the way back in 2008, but only implemented in its current form in 2017. It is a CSS feature that allows designers to create complex layouts without using tables or custom CSS grid systems.

You will need to have a basic understanding of CSS grids to fully-grasp the following section. To learn more about them, you can look at these resources online:

Like tables, grids also needs a container element, with multiple child elements each serving as a cell in the grid. Unlike tables, however, grids do not vertically-align elements with vertical-align. There are 2 main methods to vertically-align content in grids:

  1. align-items, which aligns the entire grid vertically, and;
  2. align-self, which aligns an individual cell in a grid.

a. Using align-items

Here is a very basic example of how to vertically-aligning an element using align-items, which has to be used with display: grid for it to work:

<div style="width:100%;min-height:150px;background:#eee; display: grid; align-items: center;">
  <img src="http://placekitten.com/53/53" alt="Kitten"/>
</div>
Kitten

If you are looking to horizontally-centre it too, then it gets a bit trickier; but essentially, you need to add margin:auto (more about this explained in our other post about aligning things horizontally) to the child element:

<div style="width:100%;min-height:150px;background:#eee; display: grid; align-content: center;">
<img src="http://placekitten.com/53/53" alt="Kitten" style="margin:auto;"/>
</div>
Kitten

b. Using align-self

align-self is very similar to align-items, except that it is used in individual elements, and it is used when you have multiple cells in your grid, and only want to selectively align specific cells in your grid:

<div style="width: 100%; min-height: 150px; background:#eee; display: grid; grid-template-columns: 1fr 1fr;">
  <img src="http://placekitten.com/53/53" alt="Kitten"/>
  <img src="http://placekitten.com/53/53" alt="Kitten" style="align-self:center;"/>
</div>
Kitten Kitten

Notice also, the use of grid-template-columns in the example above to specify the size of each cell.


Article continues after the advertisement:


4. Using CSS flexboxes for alignment

A closely-related cousin to CSS grids, flexbox is another great way to arrange your elements. It is a simpler version of grids that basically trades off the ability to layout your cells vertically, in exchange for more intricate options to layout cells horizontally.

If you are just looking to vertically-align 1 or 2 elements, the code is very similar to CSS grids:

a. Using align-items

<div style="width:100%; min-height: 150px; background: #eee; display: flex; align-items: center;">
  <img src="http://placekitten.com/53/53" alt="Kitten" style="margin:auto;"/>
</div>
Kitten

You can use the same margin: auto trick to centre single items horizontally too.

<div style="width:100%;min-height:150px;background:#eee; display: flex; align-items: center;">
  <img src="http://placekitten.com/53/53" alt="Kitten" style="margin: auto;"/>
</div>
Kitten

b. Using margin: auto

With multiple elements, if you want to individually align each item horizontally, you can simply assign margin:auto to each of your elements under the flexbox, though this will center the item both horizontally and vertically.

<div style="width:100%; min-height:150px; background:#eee; display:flex;">
  <img src="http://placekitten.com/53/53" alt="Kitten" style="margin:auto;">
  <img src="http://placekitten.com/53/53" alt="Kitten" style="margin:auto;">
</div>
Kitten Kitten

If you wish to use classes instead of pure CSS as shown above, Bootstrap has a section dedicated to flexboxes, which a large variety of classes available.

5. Using Bootstrap 4 and up

The easiest of the many ways to vertically-align your items, however, is to simply use Bootstrap’s Grid System to layout your content, because vertically-aligning your items is in-built into the system. The Bootstrap Grid System uses flexbox, and makes an otherwise very complex mechanism (i.e. the CSS flexbox) very easy to use, so do check it out.

6. Conclusion

Note that this article offers a very cursory look at how the CSS grid and flexbox features can be used. They are very complex mechanisms that can be used for all kinds of stuff, so be sure to give them a more thorough look after you’re done with your assignments.

If we missed out a way to vertically-align your elements (or if you have an assignment that requires you to vertically-align more complex structures), feel free to share it with us in the comments below, and we will add it into the article!

Special thanks to placekittens.com for providing the kitten images in this post! No kittens were harmed in the making of this article.

Leave a Reply

Your email address will not be published. Required fields are marked *

Note: You can use Markdown to format your comments.

This site uses Akismet to reduce spam. Learn how your comment data is processed.