CodeNewbie Community

Cover image for Centering vertically and horizontally with CSS
Álvaro Montoro
Álvaro Montoro

Posted on • Originally published at alvaromontoro.com

Centering vertically and horizontally with CSS

This article will show five different ways of centering vertically and horizontally with HTML+CSS, presented in chronological order: from how it was done in the past (which we should avoid now) to the modern ways of centering content in the present.

If you prefer to watch a video version of this article, visit my YouTube channel:

There may be other ways of centering (e.g., using margin: auto), but for simplicity and to give some background on how things have evolved, I'm going to center only on these five:

  1. Using tables
  2. Using negative margins
  3. Using translations
  4. Using FlexBox
  5. Using Grid

During our interview process, I asked candidates to center vertically and horizontally an element on the page, and most people could not give a proper answer. Hopefully, this article will help with that.

Using tables

Note: Do not use this method.

At the very beginning, when there was not an easy way to center elements, we used tables to center vertically and horizontally. Of course, this is a terrible way of doing it, but it was the only option available at the time.

The idea was to add a table that had a single cell, and center that cell vertically and horizontally:

<table>
  <tr>
    <td>
      Centered content
    </td>
  </tr>
</table>
Enter fullscreen mode Exit fullscreen mode
table {
  width: 100%;
  height: 100%;
}

td {
  vertical-align: center;
  text-align: center;
}
Enter fullscreen mode Exit fullscreen mode

This method is wrong for many reasons:

  • It is too verbose: it requires too many (additional) elements to achieve the content centering.
  • Bad use of semantic HTML: the elements are used for how they look and not by what they mean.
  • It is not accessible: related to the point above, it uses a table for layout instead of displaying data.

For those reasons, this method was not a good idea. So we stopped using it and moved to something better.

Using negative margins

Note: Avoid this method.

Then, we moved to position elements in an absolute form to 50% of the container vertically and horizontally, and then applied a negative margin of half the height and width to the top and left, respectively:

<div>Centered content</div>
Enter fullscreen mode Exit fullscreen mode
div {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 200px;
  height: 60px;
  line-height: 60px;
  margin-left: -100px;
  margin-top: -30px;
  text-align: center;
}
Enter fullscreen mode Exit fullscreen mode

This method is better than the previous one, but it also has some drawbacks:

  • Needs some pre-work: we need to know the element's size beforehand to set the proper negative margins.
  • May affect the layout: changing the margins may impact the position of the surrounding elements, line-height could cause problems with multiline, etc.
  • Still too verbose: this method requires many CSS properties to center the content properly.

Some people may say, "you can use CSS variables and the calc function to avoid those issues," and they will be correct... now. But back then, CSS custom properties were not supported by that many browsers, and the support for calc was slightly better.

And yet, we still need to specify a width and height, which is not always possible. So we would end up with "magic numbers" in the code.

Using translations

This method is close to the previous one. The idea is to absolute-position the element to 50% top and left, and then translate it by half its size using a transform:

<div>Centered content</div>
Enter fullscreen mode Exit fullscreen mode
div {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
Enter fullscreen mode Exit fullscreen mode

The percentage in the translation is relative to the element's size. So by translating -50%, we are translating half its size to the left and top, respectively. No need to know the elements' size.

This was a common way of centering elements horizontally and vertically for a while. I like it because it is straightforward (just four CSS properties). In addition, it doesn't depend on any other element (although you may need a position in the container) or on additional HTML elements.

One con of this method is that by using position: absolute, we are getting the element out of the normal flow of the page. Combined with the transform, this may cause the element to overlap other things on the page.

Using FlexBox

The previous method has worked for a long time, and it can still be handy. But then, out came new ways of laying out content in CSS: Flexbox and Grid. And they offer a world of possibilities for positioning and alignment of content (not only centering.)

The interesting thing about centering with FlexBox (and Grid) is that the styles go in the container instead of the element itself:

<div>Centered content</div>
Enter fullscreen mode Exit fullscreen mode
div {
  display: flex;
  align-items: center;
  justify-content: center;
}
Enter fullscreen mode Exit fullscreen mode

This can be seen as a more "natural" approach to laying out content. It will work with one or multiple elements (the children of the flexed container) and provide more options than the previous methods.

One issue of this method may happen when centering multiline content. The text will still be left-aligned by default, and it may not give the impression of being centered. That's because what's centered is the element in itself and not its content. In some cases, you may need to do text-align: center to center everything fully.

Using Grid

With grid, we can apply the same properties as with FlexBox, just changing the value of the display from flex to grid, and it will all work the same:

<div>Centered content</div>
Enter fullscreen mode Exit fullscreen mode
div {
  display: grid;
  align-items: center;
  justify-content: center;
}
Enter fullscreen mode Exit fullscreen mode

The idea is to have a grid with a single cell and absolute center within it (kind of like what we were doing with the table, but this time with proper semantics and without additional HTML elements involved.)

Then, we can combine align-items and justify-content into a single property: place-items, making things slightly shorter:

<div>Centered content</div>
Enter fullscreen mode Exit fullscreen mode
div {
  display: grid;
  place-items: center;
}
Enter fullscreen mode Exit fullscreen mode

Yes, just two lines of CSS can help you center content vertically and horizontally. It is not as complicated as the mechanism of some window blinds ;)

The Grid and FlexBox method may present some challenges when more than one element is inside the container. A simple solution would be to wrap all the content in additional tags in those cases. But, in general, that won't be needed.

Conclusion

Knowing how to center in CSS is a practical and valuable skill. You will need to use it at some point in your web development career. And, as we have seen in this article, it is not that complicated.

You can use any method you want to center horizontally and vertically (but please avoid using tables for layout.) I normally use transform: translate(-50%, -50%) (#3) and FlexBox/Grid (#4 or #5) depending on the situation.

I like how, in the translation solution, the element only "depends on itself," with the styles applied to the component that is centered (although the parent may need to have a position set.) While in the FlexBox/Grid method, the styles go in the parent, and the element is oblivious to the positioning. It just is, which is beautiful and a more natural way of doing it.

Interview tip: If they ask you to center an element horizontally and vertically during an interview (or in a task at work), but it only centers horizontally after applying the FlexBox/Grid methods. Check that the parent has a height ;)

Discussion (1)

Collapse
nftcryptomix profile image
nftcryptomix

Thanks for the share, I just learnt all this in a 12 hour bootCamp - Thanks