Absolute Positioning and Horizontal/Vertical Centering

Horizontal centering of an element is something that we, as web developers, do every day. It’s often an integral part of our designs. It’s easy with text and with relatively positioned block and inline-block elements. The problem arises when we try to center an element (horizontally or vertically) that is absolutely positioned. When I teased this post on Twitter, I received at least 10 replies saying that’s easy if you know the width of the child element. But that isn’t a limitation. Even if you don’t know the width, fear not! It’s actually really easy. *gasp*

When we want to center relatively positioned elements, a simple margin: 0 auto; normally does the trick:

Go ahead, resize your browser window. The blue box stays centered in the parent as long as the parent element is wider than the child element. The CSS on the child element is:

.child-element {
  width: 100px;
  height: 100px;
  background: blue;
  margin: 0 auto;
}

When you apply position: absolute to the blue box, it breaks the horizontal centering:

The cheaters’ way to center this element, since we know it’s 100px wide, is to apply the following CSS:

.child-element {
  position: absolute;
  width: 100px;
  height: 100px;
  left: calc(50% - 50px);
  background: red;
}

This works fine until you change the width of the child element. Click here to change the red box’s width. As you can see, it’s no longer centered.

So the question is, “How do you allow for an element to be both dynamically sized and horizontally centered? It’s easy, and it works all the way back to IE9! Use CSS 2D transform. Here is the solution in action:

This is a long sentence of content.

As you can see, it’s centered. If you click here to change the content of the yellow box, it stays centered! The CSS is simply:

.child-element {
  position: absolute;
  background: yellow;
  left: 50%;
  transform: translate(-50%,0);
}

The left and transform css work together like this:

  1. The left: 50%; tells the element to line up it’s left edge at the 50% mark. Obviously, the element isn’t centered, but it’s left edge is.
  2. The transform: translate(-50%,0) moves the element back to the left 50% of the width of the element. That means we’ve now centered the element!

HOW AWESOME IS THAT?!? But that’s not all. You can apply this same set of CSS to VERTICALLY center an element.

This is sample text to display the power of using transform: translate to center text (both vertically and horizontally).

By simply changing the CSS to be transform:translate(-50%,-50%), we both vertically and horizontally center the child element. True, hack-free vertical centering that works back to IE9! Click here to see it in action by changing the width of the green box.

But wait, there’s more! This method works equally well for vertically centering RELATIVELY POSITIONED ELEMENTS. Don’t believe me? Check out the box below and click here to change the orange element’s width.

This transform:translate trick works on relatively positioned elements, such as this box.

The CSS for the above example is:

.child-element {
  position: relative;
  left: 50%;
  top: 50%;
  transform: translate(-50%,-50%);
  background: orange;
}

Of course, using 2D transforms still requires the -webkit- and -ms- prefixes, but it’s vertical and horizontal centering that works back to IE9 on almost any element.

Like this? Hate this? Angry at me for finding this awesome trick? 🙂 Let me know in the comments or tweet me at @joshbroton.