Facundo Corradini Frontend developer, CSS specialist, best cebador de mates ever.

13 ways to vertically center HTML elements with CSS

5 min read 1505

13 Ways To Vertically Center HTML Elements In CSS

Editor’s note: This post was last updated on 13 September 2021 to improve code and update any outdated information.

Back in the good old days, the limits of CSS made even “simple” things like vertical centering a challenge, with some developers even relying on JavaScript solutions. It was fragile, it was very constrained, and there was always that one exception that made it fail.

Whether we were trying to align an icon or image beside the text, create one of those popular hero banners, or creating a modal overlay, centering things in the vertical axis was always a struggle.

But CSS has come a long way since, providing lots of methods that made vertical centering easier every time. Here’s a summary of some of them, along with their use cases and limitations.

1. Absolute positioning and margin: auto

An element with no intrinsic size can be centered by simply using equal values from the top and bottom. When an element has intrinsic dimensions, we can use 0 for top and bottom, then apply margin: auto. This automagically centers the element:

.container{
  position:relative;
}
.element{
  position:absolute;
  top: 0; bottom: 0; left: 0; right: 0;
  margin: auto;
  height: 20px; /*requires explicit height*/
}

We’ve added additional styles in the CodePen to make the demo more presentable.

See the Pen
Centering 1: absolute positioning
by Facundo Corradini (@facundocorradini)
on CodePen.

The limitation is, of course, that the element height must be explicitly declared, or it will occupy the entire container.

We made a custom demo for .
No really. Click here to check it out.

2. The classic top:50%, translateY(-50%)

This is one of the first tricks, and still a go-to, for many developers. By relying on absolute positioning the inner element at 50 percent from the top of their parent, we can then translate it up 50 percent of its height:

.container{
  position: relative;
}
.element{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

See the Pen
Centering 2: top 50 translateY -50
by Ibaslogic (@ibaslogic)
on CodePen.

A fairly solid approach, with the only major limitation being the use of translate that might get in the way of other transforms, for example, when applying transitions or animations.

3. Centering with tables

A really simple approach and one of the first (back in the day, everything was centered around tables), is using the behavior of table cells and vertical-align to center an element on a container.

This can be done with actual tables or using semantic HTML, switching the display of the element to table-cell:

.container{
  display: table;
  height: 100%;
}
.element{
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}

See the Pen
Centering 3: tables
by Facundo Corradini (@facundocorradini)
on CodePen.

This works even when both elements are of unknown height. The major limitation is, of course, if you need to have a noncentered sibling, it might get tricky with the background limits.

Also, bear in mind this totally fails on screen readers (even if your markup is based on divs, setting the CSS display to table and table-cell makes screen readers interpret it as an actual table). Far from the best when it comes to accessibility.

4. The ghost element method

Another oldie that didn’t catch up for whatever reason is using inline-block with a ghost (pseudo) element that has 100% height of the parent, then setting vertical-align: middle for both the pseudo-element and the element we want to center:

.container::before {
  content: '';
  display: inline-block;
  height: 100%;
  vertical-align: middle;
  margin-left: -0.5ch;
}
.element{
  display: inline-block;
  vertical-align: middle;
}

See the Pen
Centering 4: ghost element method
by Ibaslogic (@ibaslogic)
on CodePen.

It actually works quite well, with the most noticeable “gotcha” being that it moves the horizontal center just a tiny bit to the right because of the always cringy behavior of whitespace between inline-block elements.

This can be dealt with by adjusting the margin on the pseudo-element. In our case, we’ve assigned margin-left: -0.5ch. We can also get a perfect centering by setting the font size to 0 on the container and then resetting it to px or rem on the element:

.container {
  font-size: 0;
}
.container::before {
  ...
/*   margin-left: -0.5ch; */
}
.element{
  /* ... */
  font-size: 16px;
}

5. Using margin: auto on a flex item

Finally getting into modern CSS territory, Flexbox introduced a pretty awesome behavior for auto margins. Now, it not only horizontally centers an element as it did in block layouts, but it also centers it in the vertical axis:

.container{
  display:flex;
}
.element{
  margin:auto;
}

See the Pen
Centering 5: margin:auto on a flex-item
by Facundo Corradini (@facundocorradini)
on CodePen.

This tactic is one of my favorites because of its simplicity, the only major limitation is that it’ll only work with a single element.

6. Pseudo-elements on a flex container

Not the most practical approach in the world, but we can also use flexible, empty pseudo-elements to push an element to the center:

.container{
  display: flex;
  flex-direction: column;
}
.container::before,
.container::after {
  content: "";
  flex: 1;
}
.element{
  /* ... */
  margin: 0 auto;
}

See the Pen
Centering 6: pseudos on a flexbox
by Facundo Corradini (@facundocorradini)
on CodePen.

This can be useful when we want to keep flexible spacing on a column-oriented flex container with multiple items.

7 and 8. Align on the flex container or the flex item

Flexbox also introduced really great alignment properties (that are now forked into their own box alignment module).

This allows us to control how items are placed and how empty space is distributed in ways that would have required either magic numbers in CSS for a specific number of elements (or clever JavaScript for dynamic amounts).

Depending on the flex-direction, we might use justify-content or align-items to adjust as needed.

On the container:

.container{
  display: flex;
  justify-content: center;
  align-items: center;
}

See the Pen
Centering 7: align on flex-container
by Facundo Corradini (@facundocorradini)
on CodePen.

On a particular flex item:

.container{
  display: flex;
}
.element{
  align-self: center;
  margin: 0 auto;
}

See the Pen
Centering 8: align on flex-item
by Facundo Corradini (@facundocorradini)
on CodePen.

There are not many downsides to this, except when you need to support older browsers. IE 11 should work, but its implementation of Flexbox is quite buggy, so it should be always treated with extra care.

IE 10 requires additional work that has different syntax and requires the -ms vendor prefix.

9 and 10. Align on the grid container or the grid item

CSS grid includes pretty much the same alignment options as Flexbox, so we can use it on the grid container:

.container{
  display: grid;
  align-items: center;
  justify-content: center;
}

See the Pen
Centering 9: align on grid-container
by Facundo Corradini (@facundocorradini)
on CodePen.

Or just on a specific grid item:

.container{
  display: grid;
}
.element{
  justify-self: center;
  align-self: center
}

Lack of legacy browser support is the only limitation of this technique.

See the Pen
Centering 10: align on grid-item
by Facundo Corradini (@facundocorradini)
on CodePen.

11. Pseudo-elements on a grid

Similarly to the Flexbox alternative, we can use a three-row grid with pseudo-elements:

.container{
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: repeat(3, 1fr);
}
.container::before,
.container::after{
  content:"";
}

Remember that 1fr actually means minmax(auto, 1fr), so the empty rows will not necessarily take one-third of the container height. They will collapse as needed all the way down to their minimal value of auto, and without content, means 0.

See the Pen
Centering 11 : grid + pseudos
by Facundo Corradini (@facundocorradini)
on CodePen.

This might look like a silly approach, but it allows us to easily pull off one of my favorite CSS Grid tricks: combining fr rows with minmax ones, which causes the empty fr ones to collapse first, followed by the mixmax ones.

So, having the pseudos take the fully-collapsible rows allows the auto-placement algorithm to work its magic on our actual elements, except if we need to support IE, which lacks auto-placement. Which, leads us to the next method…

12. Explicit grid row placement

CSS grid allows items to be explicitly placed on a specific row, so the same grid declaration as above and the item placed on the second row will be enough:

.container{
  display:grid;
  grid-template-columns:1fr;
  grid-template-rows: repeat(3, 1fr);
}
.element{
  grid-row: 2 / span 1; /* or grid-row: 2/3 */
}

This can work down to IE10. Believe it or not, IE was one of the first and stronger supporters for CSS grid, shipping it all the way back in 2011 with IE10. It has a completely different syntax, but we can make it work:

.container{
  display: -ms-grid;
  -ms-grid-rows: (1fr)[3];
  -ms-grid-columns: 1fr;
}
.element{
  -ms-grid-column: 1;
  -ms-grid-row: 2;
}

See the Pen
Centering 12 : explicit placement on a grid
by Facundo Corradini (@facundocorradini)
on CodePen.

13. margin: auto on a grid item

Similarly to Flexbox, applying margin: auto on a grid item centers it on both axes.

.container{
  display: grid;
}
.element{
  margin: auto;
}

See the Pen
Centering 12 : Margin auto on a grid-item
by Ibaslogic (@ibaslogic)
on CodePen.

Some (probable) future implementations

According to the CSS Box Alignment Module Level 3 specification, align-content should work on the block axis of block containers and multicol containers, so (if browsers implement it) we should be able to center the content of those containers just like we do in flex or grid containers.

Conclusion

And that’s it. What was once extremely hard can now be achieved in a dozen-plus different ways, and I’m probably missing a couple more. If you know other techniques, please share them in the comments.

Facundo Corradini Frontend developer, CSS specialist, best cebador de mates ever.

7 Replies to “13 ways to vertically center HTML elements with CSS”

  1. Dude i was going nuts and completely forgot Flexbox works so well! ANother tip would be to Use inline-flex so there isn’t all the weird spacing!

  2. God bless you dude. I’ve seriously been stuck on this for over 2 hours and your blog post solved my problem like it was nothing

Leave a Reply