Tough Fucker© – The Ultimate CSS2 Vertical Centering Monster

update: 7/5/2013 – Updated demo to include both 100% width and specific width examples.

update: 30/4/2013 – Fixed for page scaling

When all of your orthodox CSS level-2 vertical centering hacks have failed, what do you do?
That’s right, you’re fucked. Might as well export the whole page as a jpeg.
Now let’s be real – flexbox is a messiah, but it’s also miles away.
Time to bring in the big guns.

Before you meet The Man, let’s iterate over your existing options.

  1. Line-height. Talk about a single text line/element display porn limitation.
  2. Position: absolute, top: 50% and negative margin-top. Talk about a fixed height requirement.
  3. Display: table-cell, vertical-align: middle. Talk about table not being a block element and fucking up.

It is likely that in most cases, some of these old world “lunch with your parents” methods fit your scenario. Congrats. But what if your shit is a complex object with many inside CSS dependencies? Something that breaks table-cell’s weakly hanging neck like a twig? Meet the ultimate CSS vertical centering monster – the Tough Fucker©.

Demo here

.tough-fucker { /* time to call The Man */
  display: inline-block;
  vertical-align: middle;
  width: 0;
  height: 100%;
  min-height: inherit;
  max-height: inherit;
  padding: 0;
}

.wrapper {
  font-size: 0; /* kill the inline-block white-space */
  letter-spacing: -1px; /* http://stackoverflow.com/a/6351697/759144 */
}

.centered { /* the element to center */
  display: inline-block;
  vertical-align: middle;
  letter-spacing: normal;
  font-size: 16px; /* overpower the parent font-size: 0 */
}
<div class="wrapper">
  <span class="tough-fucker"></span>
  <div class="centered">
    <!-- this shit is vertically centered relative to .wrapper parent -->
  </div>
</div>

That’s right, Tough Fucker© is an extra element – he sets the standard for other elements to follow using maximum parent height, display: inline-block and vertical-align: middle. It goes without saying that he comes first. Any other elements no matter their height will follow as long as they’re inline-block and vertical-aligned middle. Why the negative margin? Because shut up.

update: This was revealed to be problematic with the pixel margin and page scaling. Since CSS3 white-space-collapse/bikeshedding is not an option yet, font-size 0 on the .wrapper element is required. Or you can eliminate white-space from your fucking code, nobody cares about it anyway. All code samples and demo have been updated.

Anyway, this is what Tough Fucker© is about:

  • The centered elements can have flexible height
  • The centered elements can be very complex
  • Compatible with IE8 upwards
  • Badass

Shut the fuck up. Your HTML is a putrid mess and you know it. While your pityful DOM manipulation scripts mash the semantics to shits, it’s being fisted by 3rd party DOM injects, faceganked by whatever the lovely widget and JS library you’re using and when the crawlers come, they take a piss on the whole thing.  If you wanted “clean”, you should have been a hairdresser. Besides, a span has no semantical meaning. Make it a div for all I care.

Still here? Swaggy little fucker, ain’t ya… Very well then.
Here’s your hipster bleeding edge pseudo-element version of The Man:

.wrapper:before {
  content: "";
  display: inline-block;
  vertical-align: middle;
  width: 0;
  height: 100%;
  min-height: inherit;
  max-height: inherit;
  padding: 0;
}

To keep the explanation simple for the iPhone crowd, let’s just say the world isn’t perfect. Not even the Tough Fucker© is, however unreal that may sound. As mentioned, Tough Fucker© can only help center other inline-block elements. You wanna sing his song you better learn his notes. The bright side is that inline-block is cool enough, it’s not a fucking table with all it’s hipster emo behavior.

Stay classy and test your fucking code.

Licence: WTFPL

  • Putin

    I loved this article. Wrangling with css and html the old way in order to retain compatibility often feels a bit like being abused. All i want to do is vertical center, man, that’s all I want! Thanks for posting this, I hope T.F. can deliver! FU html!

  • Edmund O’Connell

    Pure genius. It is BS that achieving this in CSS3 is so non trivial. But nevermind, this solution works a treat and had the benefit of being amusing to read.

  • It seems to fail in Firefox 20 when you Ctrl-+ to increase the zoom. The entire orange section drops to the bottom of the page until you reload the page.

    • mystrdat

      You’re right and it’s not just Firefox. I’ll look into it once I get some time.

    • mystrdat

      Now fixed.

      • Great! It works as expected.

        Unfortunately, if you use Ctrl – to zoom out the yellow bar is cut off at the right side at the smallest zoom level (1080p maximized Firefox 20.0.1). The red area looks like a U rotated 90 degrees counter-clockwise.

        • mystrdat

          Can you provide a screen? I don’t see any strange behavior anymore.

          • Here is the screenshot you requested. As you can see, the yellow bar has a gap near the right side. If I zoom even more, the gap gets wider.

          • mystrdat

            I see, thanks for the screen. Inline-block elements don’t expand to 100% width of their parent, so the demo only goes as far as the text content does. I don’t really consider this a bug as you don’t necessarily need to center a full width element, but if you wanted it to expand to full parent width, you could use width: 100% on the .centered element. In the demo, this would cause padding to overflow the screen, so box-sizing: border-box would be an adequate correction. I’ll add that to the code so it’s hopefully more clear. At the same time, I should probably add a second element that would address specific width elements too.

            Edit: Updated the demo.

  • CS

    Great article and solution! Thanks for covering some of HTML’s biggest pain points.

  • biaaaaatch

    you’re a funny fucker.