Centering All The Directions

Since the dawn of civilization, mankind has struggled and strived, against all odds, to achieve that next level of human evolution; to stake out our place on this great planet, and in the universe around us; to boldly go where… Oh, never mind the hyperbole.

I would like to say, “Raise your hand if you’ve ever struggled with centering content in CSS, especially vertically?” But it’d probably be quicker to say, “Raise your hand if you haven’t struggled with…” CSS is an amazingly powerful tool, but there are some things, like vertical centering, that remain “too hard”™ even to this day. I’m going to explore various ways we center things, but propose we still need something better.

<center>

First off, if you’re still using <center>  tag to center things, 1999 called, and they want their website back. Seriously, hand in your “modern web developer” membership card. You’re welcome back here once you’ve rid your code of this beastly monstrosity.

text-align:center

When it comes to centering text, you really can’t beat text-align:center. It does exactly what’s advertised on the box. It horizontally centers inline text within a parent container.

Example:

Hello World

 
Well, that was easy. The technique here is to instruct a parent element that we want its content (text) to have a certain positioning. We don’t directly style the content in question, but its container.

Except, this method only works on inline elements (and probably should only be used on text, but it’s not strictly limited there). And it only works in the horizontal direction.

vertical-align:middle

“But, but…” you say. “But what about vertical-align:middle?” Yeah, sounds like our solution. Turns out, not so much.

Unlike text-align:center, which is set on a parent element to describe how to center its content horizontally, vertical-align:middle goes on the content element itself, and doesn’t describe its position in its parent, only its position with respect to other inline content around it.

Yeah, useful for making inline text and inline images work nicely side-by-side, but it’s not the mystical veritcal centering we’d like.

Note: You can use this trick with display:table on the parent and display:table-cell on the content element. Downsides: It’s back to tables, and it has poor legacy IE suppport.

line-height

A useful trick for vertically centering inline text is to set the line-height property of its container to the desired height, and the text should (roughly) vertically center itself. This is a common trick. Sometimes there are side effects to your line-height setting, and it’s not quite perfect (because of font metrics variations, etc). But hey, when all you have is a match-stick, everything looks like a pile of wood to start a campfire, right?

So, what do we do for centering of a block-level element?

margin:auto

Well, technically, we’d probably use margin: .. auto where “..” was our vertical margin (we’ll come back to vertical in just a moment).

How does it work (horizontally)? Example:

Hello World

 
NOTE: Because in this example I’m not defining an exact width for the #ex2_content element (I only want it to be as big as the text needs), to make it shrink/collapse around the text but still be center-able, I use display:table . You might think display:inline-block would work, but it doesn’t. But if you manually set the width or even max-width on #ex2_content, you don’t need to set display:table at all.

Cool, huh? Here, we just tell the content directly that we want it to center itself within its parent, horizontally of course. This is a little less semantic than text-align:center because you’re sort of describing the space around the content rather than controlling the content itself. But we’ll give CSS a pass on that one. It’s not too bad.

So, you say: “Surely, that must work vertically, too!?” No, how idiotic are you for hoping for such a symmetric and simple solution!? Seriously, in what bizarre world did you learn CSS!?

Unfortunately, for reasons beyond mortal understanding, this “trick” doesn’t work in the vertical direction.

hacks, hacks

There are lots of other hacks which involve exotic things like negative margins, phantom extra  ::before elements, and other crap. Most of them are quite brittle if your content is not of fixed-size.

If nothing else, it’s proof that we are a creative species when pressed for survival — we find a way to make it.

translate(-50%,-50%)

Hats off to Chris Coyier at CSS-Tricks.com for a recent hat trick reveal: using position and translate.

If you set position:absolute on some child element, then set left:50%; top:50% on that child, its top-left corner will be centered both horizontally and vertically. Duh, we probably all knew that. But that’s not helpful because our content is almost never just 1×1 pixels.

The trick then, is translate(-50%,-50%). Whereas most percentage calculations of this nature, like left and top, are of the parent container’s metrics, the percentages in translate(X,Y) are of the element itself.

So, we position the top-left corner in the middle of our container, and then “shift” it back half its width and half its height, and boom, magically it’s centered in both directions!

Example:

Hello World

 
This trick is certainly much more robust than some of the other hacks, because it gracefully responds to all the various conditions, like non-fixed-size content, min-width, max-height, overflow:scroll, etc. It basically does exactly what you’d hope it would do. It shrinks or grows (unless you constrain it), but stays centered regardless. Nice!

Go play around with it and see what it can do.

But, let’s be honest: it’s quite less semantic, and a bit uglier syntax-wise (especially because of those pesky vendor prefixes). And it falls into that category of over-compensation.

It’s probably the best technique out there so far, all things considered. But it makes me sad that we still have to write articles like this, and trick CSS into doing what we want.

Is that the best we can do?

If all these “tricks” and “hacks” sound like “junk science” to you, you’re not alone. Why is this so darned difficult? Why do we have to use different techniques for different scenarios?

What about one content positioning rule “to rule them all”? Shouldn’t there just be a standardized “thing” added to CSS to handle all the cases, instead of the hackery we currently have?

(conspiracy theory: CSS standards folks need to continue to fuel the fire of bloggers, so they leave some things unsolved on purpose!)

Here’s a modest proposal I just came up with:

I’m suggesting here a content-positioning property on the parent element which controls the positioning of its child element(s). And content-positioning-anchor controls where the registration point is on the child element(s). It would, of course, default to 0px 0px, but if you set it to 50% 50%, you’d be saying, essentially, “put the middle of my content in the middle of my container.”

Bam! I just solved all the world’s problems. Well, not really. This hyperbole thing is addictive.

What do YOU think?

Let’s discuss what a single-unified-solution would have to look like. Or maybe there’s already super-secret CSS standards proposals for this that I’m not aware of. In any case, let’s dispense with the hackery and move towards standardization of this all-too-common use-case.

What do you think? Tell us!

  • http://getify.me/ getify

    One big note:

    I intentionally left out of this article the discussion of “flexbox”, mostly to not further complicate the overall point. Let me explain why I don’t consider it a “suitable” solution (any more so than any of the other hacks mentioned above).

    1. flexbox is an enormously powerful CSS functionality with lots of moving parts, and was designed primarily to create a layout mechanism for sites that need to be able to reorganize content “blocks” based on screen orientation/size. It describes things in terms of flex items on lines and cross axis’ and stuff like that.

    The simple task of centering an item IS possible with flexbox, but it’s conflated with a lot of other flexbox’ness, and resembles a side-effect hack similar to the above suggested hacks. I don’t think it achieves some semantic purity that we’ve finally been needing. It’s yet another shoehorn+shoe.

    2. flexbox being a layout mechanism puts it, in my mind, more in the realm of doing things like `display:table` and `display:table-cell`. Those things already work, and you CAN achieve centering with them. But we’d probably all agree that you’re abusing a legacy side effect of tables. I feel the same way about flexbox as a solution to centering.

    3. My proposal actually gives a LOT more flexibility to the task of centering than flexbox does, because you can pick where the child content’s anchor point is, in pixels, percentages, keywords, etc. You can do a lot more than just “center”, you can control precisely the positioning of child content.

    In the same way that CSS transforms let you specify the registration point for the transform to happen about, sometimes you want to offset some item 10px off center or something like that, and with my proposal, you have that control. With flexbox, you do not.

    • Chris_Krammer

      I think Flexbox is a really powerful technique and I really can’t wait until it’s ready to use – because unfortunately it isn’t yet. What’s such a layout method worth if it just works in IE10 and above?
      Apart from that the whole syntax is a mess, since you have to use the old and the new notation and a dozen of vendor prefixes.
      Furthermore the old syntax is quite slow in terms of paint speed. So, Flexbox is nice, but far from ready. I’m in quite a lucky position that I only have to deal with WebKit in our mobile apps, but even here it’s almost useless due to it’s sloweness, because at mobile every millisecond counts. So I often rather use another method than Flexbox.

      • Bruno Racineux

        As long as you don’t need wrapping from flexbox, the model can work up to Safari 3.1 and FF3.6, and Opera Presto + IE8 (desktop size) with tables + table-cells fallback.

        I successfully made my first responsive site attempt with it. And while it was a huge pain, I have a pretty good model moving forward.

        So technically it can be ready to use. Granted it’s not very pretty css, and the static cross-browser css file need quite a few hacks.

  • Cory Chase

    Great write-up, thanks for sharing!

    I wonder if the concept of a content-position wrapper is really necessary. How about extending the position property to work with a position-anchor, that way devs wouldn’t change much in their process with the whole relative/absolute song and dance and all browsers would be at least quasi-functional out of the gate.

    • http://getify.me/ getify

      I actually did think about that, but it seemed like the potential for immediate breakage of sites (since they’re all used to the anchor-point being top/left) was pretty high.

      The issue is, if we’re trying to “solve” centering, it’d be nice if the defaults were “middle middle” or “50% 50%”, so you’d obviously have to opt-in to having this new anchoring apply to an element. The “opt-in” I suggested was using a new property on the parent.

      The other way, which puts still slightly more work on devs who want to center, is that anchor defaults to “top left” (“0% 0%”), and is always on and relies on `position:absolute` or `position:relative` as the opt-in, and then devs just have to change the content-anchor on children to get centering.

      Either way, I think this could be really helpful to get added into CSS. :)

    • http://www.morganfeeney.com/ Morgan Feeney

      I totally agree with Cory. Why add more code than would be needed? At the same time it makes the process less complicated. I would stick with the relative/absolute relationship between parent and child, but I’d have the positioning like this:

      position: absolute-center

      If you wanted to offset by 10px left then use margin like it would normally be achieved.

      • http://getify.me/ getify

        margins never apply on absolutely positioned items. :)

        • http://www.morganfeeney.com/ Morgan Feeney

          Hey Getify, I just tried a few “experiments” to see, as I have used negative margins before on absolutely positioned elements and they did the job, it may however not be inline with W3C standards if that is an issue?

          http://codepen.io/mofeenster/pen/ocIdn

          I also centered a dive with padding, dunno if it is any good or not:

          http://codepen.io/mofeenster/pen/DrGhq

          • http://bowdenweb.com/ J. Albert Bowden II

            negative margins validate; the example you created does not, but that’s because of codepen’s styles. pasting your styles into the direct input tab will pass validation.

          • http://getify.me/ getify

            @Morgan-

            Here’s what your margin attempt looks like in my Firefox: http://gyazo.com/e2e89e91e036409b98d69c25d675a0a9

            Also, keep in mind that negative-margins requires manually specifying the dimensions, like -327px, whereas the translate() trick lets you use -50%. THAT is the main thing that makes the translate() hack slightly better of a hack… but still a hack.

          • http://www.morganfeeney.com/ Morgan Feeney

            @getify:disqus that is how it is supposed to look, I added a -200px margin to demonstrate that margins can be used for the positioning of absolutely positioned stuff. If you edit the pen and remove the margin you will see a centered div.

            You can still use a percentage for the negative margin.

            The height is an issue however and if not stated will not be centered vertically.

          • http://getify.me/ getify

            @morganfeeney:disqus OK, but the only reason your example “works” without the margin is because you manually calculated that if your inner box is 50% width and height, then left/top should be 25%. That’s what I meant by saying that the coordinates have to be manually calculated with these types of hacks. If your inner box changes its dimensions, you have to manually change the positioning.

            The translate() trick keeps the box automatically positioned, no matter how big or small it shrinks, because the -50% for translate means “half of my size” NOT “half of my parent’s size” like all the other props (left/top/width/height).

          • http://www.morganfeeney.com/ Morgan Feeney

            @getify:disqus cool, I just created a pen with your code and yes it works really well. Even if you add padding etc it still stays centered, I like it.

          • http://getify.me/ getify

            I don’t think `height` is required on the child element. Check out: http://jsbin.com/etupoz/1/ and remove the min/max heights from the `#p2` element, and it still stays centered. :)

          • http://www.morganfeeney.com/ Morgan Feeney

            Hey @getify:disqus did that, but then added more content and it broke the layout: http://jsbin.com/etupoz/53/edit

            it would be good if the parent element acted like a float and didn’t need a specific height, so it just grew to the size of the content.

            Thinking about context here, and you may have mentioned it previously so forgive me if that is the case, where would this get used? Or what specific instance would be best for it to be used on? e.g. an image as the dimensions won’t change, or text (or both), which could break the layout if it is responsive for example.

          • http://getify.me/ getify

            broke it? looks reasonable to me. perhaps you wanted to add a max-height to the blue content box?

            or are you saying you want the content to grow until it’s too tall, and then start stretching the parent? I dunno how to do that. :)

          • http://www.morganfeeney.com/ Morgan Feeney

            Hey @getify:disqus I succumbed to your method, check it out: http://pensioncenter.co.uk/ the three circles near the bottom on the home page.

            It was the best way, I then used conditional classes for making it work in ie8, ie7, I had to anyway as it is responsive.

          • http://getify.me/ getify

            Nicely done, looks really great! :)

          • http://www.morganfeeney.com/ Morgan Feeney

            Hi again @getify:disqus I have been testing that example: http://pensioncenter.co.uk/ in ie10/9/8 etc. and there is an issue. The 50% added to the left and top is adding to the overall width. Have you overcome this issue previously? If so how did you do it?

            Cheers

          • http://getify.me/ getify

            I have not seen that problem personally. But truthfully, I don’t spend much time in IE.

            Not looking very closely at the code, but maybe it’s that the parent container needs overflow:hidden, or that the parent needs to be position:relative or that the children for some reason aren’t position:absolute like you’d think they were. Just some quick things to look at and verify.

          • http://www.morganfeeney.com/ Morgan Feeney

            Hey, you are the man! Overflow hidden did it. I was trying all sorts of stuff, but that simple change is perfect.

            Thanks

  • Chris_Krammer

    Most of the time I use line-height and I also re-discovered the display: table-cell method recently. But I didn’t know about the translate-trick. Since I mostly have to only care about WebKit, I may use it regularely in the future.

    • http://getify.me/ getify

      If you look at: http://caniuse.com/#search=transform

      There’s an awful lot of browsers, even back to IE9, which support the `transform:translate(x,y)` CSS property, which means all of them can use that trick.

      But I do hope we can get to the point where we don’t have to do tricks at all! :)

      • Chris_Krammer

        Well, but what’s it worth if it doesn’t work in IE8? I think we all agree that we don’t need to support IE6 and IE7 anymore, but we can’t abandon IE8. There are polyfills of course, but just to enable this “trick”? I don’t think so …

        • http://getify.me/ getify

          I don’t support any browser versions. I think browser versions are dead.

          See http://BrowserVersionsAreDead.com

          I build to standards and let things degrade in “older” browsers as they will. So, no, I don’t find any particular sway in caring about IE8, because if things are layed out “wrongly” in IE8, that doesn’t bother me even a little bit.

          What serious life-ending crisis would there be if users in IE8 saw boxes not properly centered? I mean, really, honestly, why should we care THAT much about that? :)

          • Chris_Krammer

            If it would be so easy. ;) Generally its the past way to let things degrade gracefully, but I think you view your designs in different browser versions and fix it, if it’s far away from the “original” for let’s say in IE9. If not, lucky guy. ;) You save yourself much stress …

          • http://getify.me/ getify

            check out that talk I linked to, really. I talk all about how I think devs need to start pushing back on clients and bosses to fight against the “lie” that sites must look/feel/behave the same in all browsers. It’s a terrible perversity of our web platform to try to do that, and we’ve all been obsessed with that for over a decade. It’s time we embrace the diversity of the platform and the fact that things are supposed to look/feel/behave differently in different browsers. This is a GOOD thing, not a bad thing. :)

          • Aaron Fuller

            Here this is a far superior css that is hack free no java script required and works across aLL browsers and resizes the content to fit into whATEVER size screen layout your working with or that person viewing page is working with…

            This link will take you to page with a perfect layout structure using divs and columns,,,

            http://matthewjamestaylor.com/blog/perfect-3-column.htm

            Even works on an I-Phone!!!

          • Aaron Fuller

            No tables required!
            And oh yeah the layout works in Safari, IE6, IE7,IE8,9 AND 10, FIREFOX, MOBILE Phone Browsers, Chrome~!!! Amazingly simple yet ingenious in and of itself! Thanks Matthew~!

          • Aaron Fuller

            Here is a diagram of horizontally set menu bar that will display the content in boxes centered and center the menu in the center of page as well I also included the CSS for this one…

            The secret to centred drop-down menus is removing the overflow:hidden; rule on the centeredmenu div. Unfortunately if we simply delete this rule, horizontal scrollbars may appear on the website. This happens because the invisible ul element sometimes extends off the righthand edge of the visible page. But don’t worry, there is a solution to this. Luckily we can prevent the righthand overflow by horizontally flipping the menu elements so the ul extends off the left side of the screen instead. Here are the specific CSS changes we need to make: (bold = added, strikethrough = removed)

            #centeredmenu {
            float:left;
            width:100%;
            background:#fff;
            border-bottom:4px solid #000;
            overflow:hidden;
            position:relative;
            }
            #centeredmenu ul {
            clear:left;
            float:left;
            float:right;
            list-style:none;
            margin:0;
            padding:0;
            position:relative;
            left:50%;
            right:50%;
            text-align:center;
            }
            #centeredmenu ul li {
            display:block;
            float:left;
            list-style:none;
            margin:0;
            padding:0;
            position:relative;
            right:50%;
            left:50%;
            }
            #centeredmenu ul li a {
            display:block;
            margin:0 0 0 1px;
            padding:3px 10px;
            background:#ddd;
            color:#000;
            text-decoration:none;
            line-height:1.3em;
            }
            #centeredmenu ul li a:hover {
            background:#369;
            color:#fff;
            }
            #centeredmenu ul li a.active,
            #centeredmenu ul li a.active:hover {
            color:#fff;
            background:#000;
            font-weight:bold;
            }

            And here is a diagram of how the altered layout elements are positioned:

            Notice how the pink ul element extends off the lefthand edge of the page. When something extends off the left side it’s automatically cut off by the browser viewport so we don’t need an overflow:hidden; rule anymore. Goodbye overflow:hidden;!

          • Aaron Fuller

            Here is link to demo page for the Centered menus as well as my last post didn’t have the full article just some of it…

            http://matthewjamestaylor.com/blog/centered-dropdown-menus.html

          • ShirtlessKirk

            Why should we care?
            One word: money.
            Several words: If your target audience is using IE8 and is likely to go to a competitor because your site doesn’t look “right” then your business doesn’t make money from them using your service. That gets you fired.

            I’d rather not care myself, but I’m not in a position to say “bollocks to you users”. Nor is my company.

          • http://getify.me/ getify

            There is actually no sustainable research that I’ve found that supports the idea that users choose to buy based on the lack of layout quirks in a page. Companies convince themselves that if they pour all this effort into having perfect layout in older browsers, they’ll keep customers. But companies that have stopped caring about layout quirks have not reported declining income as a result. Companies that have done A/B testing of this stuff have not reported any relevant proof that older-browser-obsession retains revenue.

            Turns out, customers usually buy things based on the cost and suitability and availability, and all those other real-world indicators of competitiveness. The fact that your buttons are not centered or that they have too much or too little padding, compared to say Chrome 30, is all but irrelevant to them.

          • ShirtlessKirk

            It’s our A/B testing that is reporting this. However, I think it’s bullshit as it is based on analytics that are affected by a large number of variables, the day of the year being one of them.

            As an aside, I’m kicking back on new designs for a site because they look too much like an iPhone app. The fact that it was designed by a Mac user and signed off by another one is entirely coincidental, I’m sure…

  • Thomas Mazeika

    This was really helpful. I agree with the conspiracy theory (Ha!). I would think that content centering would have a property just for that… but nope!

    When you think about it, “Margin: auto;” should be able to be applied to all edges. Just like how “Margin: 5px;” puts a 5px margin around the whole box, why shouldn’t “Margin: auto;” do the same; vertically and horizontally align the box. For just vertical align, do “Margin: auto 0;”, and “Margin: 0 auto;” for horizontal align.

    Great article; good job.

    • http://getify.me/ getify

      I never quite understood why `margin:auto auto` didn’t work, but I think it has to do with how the layout algorithm works (it lays things out horizontally first, then vertically, then doesn’t recurse, or some such jazz like that).

      But unfortunately, we couldn’t just “fix” that now, because there’s probably a lot of sites that accidentally have that, and are compensating with other tricks, where it could break them if top/bottom auto-margin just started trying to vertically center.

      In either case, the thing I don’t like about `margin` as the trick is that instead of styling the content, you’re styling the stuff around the content. Seems a little indirect for my tastes. I’d like something pure and semantic, if we’re in the business of inventing stuff. :)

  • Guest

    .conteiner {display:flex} .item {margin:auto;}
    or .container {display:flex; justify-content: center; align-items:center;}

    • David

      I really like the flex-box approach but it seems to get kind of wonky on Firefox if the element is positioned absolutely.

  • http://bowdenweb.com/ J. Albert Bowden II

    lol. imo negative margins aren’t hacks….or if they are, so are negative x,y coordinates ;)

    the different techniques are simply an offshoot of having so many options for layout, each with its own special rules/details/quirks/etc. without having been there, i’m pretty sure the differences in time frames, developers, web capabilities, etc., all aided in making them that much harder to be congruent throughout. new versions of css could/should clean these up, but that’s easier said than done: it takes forever to get a new version, and the new ones have introduced new properties and modules that extend layout.

    in regards to the margin demo, i wasn’t sure if you pointed this out when you mentioned text-align, but another option instead of display:table is to set text-align:center on the parent element instead. i actually set most body elements to that, margin-left/right:auto work like a charm and you get older user agent support, even though versions are dead ;)

    i was unaware of the translate trick, that is going to be handy. i bet its based off the original negative margin demo, which actually is quite similar, give or take a few style declarations. its also an example of applying margins to an absolutely positioned element: http://bluerobot.com/web/css/center2.html

    i like your approach to a solution, but i *think* it is already in the works in css3 in the alignment properties module, under positional alignment:
    http://www.w3.org/TR/css3-align/#positional-values

    • http://getify.me/ getify

      I called both the translate() and margin tricks as hacks. They’re all hacks, which is why I propose something that’s “better” in that it would be specifically (and only!) designed to solve the positioning/centering question, no more no less.

      The spec you linked to is about flexbox. I cover flexbox in great detail in one of my comments down below. Short: I don’t think flexbox is a good option for centering. It’s no less a “hack” than the `display:table-cell`, IMO.

      • http://bowdenweb.com/ J. Albert Bowden II

        i saw where it included flexbox, but the other properties included made me think it was for layout, not just for flexbox. my bad.

        i love negative margins, so i’m totally biased.

  • Elliot Smith

    What about the flexible box model? Yes, the syntax is a mess, the vendor prefixes are annoying, it’s not supported everywhere, and generally it’s a pain to implement. But once you discover the magic formula, it’s no more of a hack (or magic) than the techniques above. In fact, you can create CSS with a “legal” (non-hacky) syntax which will do what you’re trying to do with the above (hacky) syntax. I used it for webapps-slider-puzzle and gradually got to this set of CSS rules, mainly so I didn’t have to remember the flexbox syntax: https://github.com/01org/webapps-slider-puzzle/blob/master/app/css/main.css#L119

    • http://getify.me/ getify

      I cover flexbox in great detail in one of my comments down below. Short:
      I don’t think flexbox is a good option for centering. It’s no less a
      “hack” than the `display:table-cell`, IMO.

      The whole point of this article is to move away from all these other workarounds and hacks (even the translate) and get to a real standards solution which is designed specifically (and only!) for solving the positioning/centering question, not as some weird offshoot of some other feature.

      • jaffathecake

        Using flexbox for vertical centering isn’t a hack, it’s designed for interdependent box layout based on the content of the box/boxes.

        • http://getify.me/ getify

          IMO that’s like saying `display:table-cell` isn’t a hack because table cell’s were designed to have content centered inside them.

          Flexbox may have the capability to center, but it certainly was designed for a much larger purpose than just centering/positioning. So my opinion of flexbox is that it’s using a sledgehammer to drive in a small nail.

          What I want is a simple, flexible tool for controlling positioning, and only that. I don’t want centering to come as some side effect of a much more complex layout model.

          • jaffathecake

            display:table-cell isn’t a hack if you want an element to have the display properties of a table-cell.

            Flexbox may be a sledgehammer for the nut of vertical centering, but that doesn’t make it a hack. Eg, if I used PhotoShop to resize an image, I wouldn’t say I was “hacking” PhotoShop just because I was only using a small fraction of its features.

          • http://getify.me/ getify

            If there was a tool which simply (and without nearly as much memory or cpu) did image resizing, and I had that readily accessible, and image resizing was the only task I need to complete, it absolutely would be a “hack” to use a much more complex tool when a more suitable targeted tool existed.

            I’m only hoping we can create better hammers instead of hacking our way around sledgehammers.

          • james williamson

            You do realize that you can choose exactly when, and when not, to use Flexbox in a layout, right? It’s just like any other layout model, like positioning. You can interrupt normal document flow with a flex container and then go right back to normal flow. In that manner Flexbox is actually a great choice for element centering, as it’s designed to target discreet regions within larger layouts.

          • http://getify.me/ getify

            I am well aware, and I think it’s a terrible idea.

          • james williamson

            Right, so we’re just going to have to disagree there. That being said the idea of being able to set the anchor point of an element makes me smile inside.

          • Tyler Benziger

            Want to clarify something. I concede that using PhotoShop to resize an image is overkill (not a hack) if there’s a smaller tool to perform the task. But the “intent” of PhotoShop is to edit images, so in regards to semantics we’re good right?

            BTW, if PhotoShop is already running on my machine, is it still a “hack”?

          • http://getify.me/ getify

            “…photoshop…to edit images…” Yeah, but as I bring up in my other blog post (http://blog.getify.com/tables-flex-not-the-centering-youre-looking-for/) that’s still what I call a “hack” because you’re using a sledgehammer on a pushpin.

            “…photoshop running…still a hack?” I suppose maybe not. The metaphor seems a little afar now to really argue too much further one way or the other.

  • http://www.nephilistic.com Askhari

    There’s one thing I dont really understand in your list:

    You throw off display:table for its poor IE legacy support, but advocate the pos:absolute/translate method as the best solution out there, yet this method proves even worse IE legacy support.

    Surely, the display table variant comes with drawbacks (for example when it comes to positioning inside the element), but it has definitely broader support than CSS Transforms. (table: ie8 and below / transforms: ie9 and below)

    • http://getify.me/ getify

      My mention of lack of legacy IE support for `display:table-cell` is really just a side note. It was not at all the main point. In fact, my main complaint against the table-CSS stuff is that… well… it’s tables. Tables are NOT for display layout, unless you’re doing grids of data. The fact that the table can be mimicked in CSS doesn’t make it any better in my mind. It’s still a terrible, non-semantic, side-effect hack.

      The whole point of this article is to move away from all these workarounds/hacks (even the translate) and get to a real standards
      solution which is designed specifically (and only!) for solving the
      positioning/centering question, not as some weird offshoot of some other
      feature.

      I’m not advocating for any of these hacks, although translate is “nicer” (than say the negative-margin) in that you can use % instead of hard-coded dimensions.

      • jaffathecake

        Don’t confuse display:table with . display:table IS for display layout (the clue is in the CSS property name). If you need the layout features of display:table then display:table it’s the right thing to use.

        This article and comments are in a column (on desktop), this effect is achieved using float:left. float:left was NOT designed for columns, but it works and has excellent browser support.

        In future, flexbox & grid will be the best thing to use for both centering and columns, as they’re designed for it.

        • http://getify.me/ getify

          it’s not designed for what I want. It’s a side-effect of a much more complex/powerful system which was designed primarily for responsive layout of a whole page, not vertical centering of a single element inside another. Just because I *can* use flexbox for centering doesn’t mean we should.

          Also, flexbox won’t let me do the kinds of more-complex positioning I suggested, such as something like “center – 10px”. Being able to control the registration point for positioning (like I can for transforms) would give me perfect control but would be extremely simple in the base-case (centering).

          • jaffathecake

            float:left wasn’t designed for columns either, it’s a side-effect of what it was designed for. If you’re against this, you should remove it from this site immediately.

          • http://getify.me/ getify

            I don’t run this site, so I’m not responsible for its CSS choices.

            I am merely a contributing author. While I may not be a fan of using float, the focus in this article is not about float but about using hacky-side-effects of other mechanisms to approximate centering, whereas I proposed a simple system that would give us centering/positioning directly and semantically instead of hackily.

        • http://bowdenweb.com/ J. Albert Bowden II

          float wasn’t designed for columns? i always thought it was, to emulate elements from print columns.

      • Justin Lowery

        First off, thanks for writing this article. I couldn’t agree more that vertical centering being a challenge in 2013 is totally insane. Almost all methods to do it are mediocre at best and never without side-effects.

        I would like to agree with @jaffathecake:disqus in one aspect though, and that is the use of `display: table(-cell);` for layout. Using the CSS version of “tables” is a completely different beast from using HTML “. The CSS version is specifically for presentation and just mimics the presentational behavior of “.

        I’ve even spoken at length with W3C members about using the `display: table(-cell);` and they’ve blessed the use of CSS table method for laying out sites/apps. I use it frequently for laying out complex web-app with multi-panel “column” interfaces.

        One HUGE benefit of using CSS “tables” is you can easily get equal height columns independent of content height, something that would be impossible without JS, with very little effort. So, I’d hate to write-off the use of this CSS property because of its unfortunately relationship with HTML “tables”.

        Another benefit is it has good support across browsers with IE8+, so it beats a lot of other solutions … [cough] flexbox [cough] …

        One thing about using CSS “tables” is they do have some really weird presentational side-effects that can be pretty buggy at times, and they definitely don’t solve all centering issues. But, these bugs can be solved if you know what’s causing them.

        Cheers!

        • http://getify.me/ getify

          I am well aware that the CSS world has “blessed” the use of `display:table(-cell)`. They also say, rightly so, that `text-align:center` in CSS is better than the `align=center` property in HTML. Not at all surprising that they would feel that moving table-display-semantics into CSS was “a good thing”.

          Nevertheless, I don’t see it that way, for tables.

          Here’s the supposed logic: let’s take something (table) with an awful lot of precedent and baggage and (abused) semantics, then let’s put something into CSS which has exactly the same layout-semantics, and let’s call it the exact same thing as it’s called in markup… BUT we’re going to tell everyone that they’re not really tables.

          If it looks like a duck and quacks like a duck….

          I don’t think that the fact you put table-display-semantics into CSS means that it’s anymore valid to use elements with that style against what tables were for than it was ok to abuse the markup (as most of us did for years).

          I don’t think you get to just move something from markup to CSS and then pretend that that somehow magically changes its semantics. Just because the spec maintainers say “oh, no, it’s totally cool, we intended it that way” doesn’t mean that all of us agree.

          From where I stand, tables are tables, whether they’re markup or CSS based, and they have some valid uses and other uses that are not valid.

          • http://www.nephilistic.com Askhari

            Let’s cut this discussion short – I think it’s a point worth debating, it brings advantages and disadvantages, but theres is one technique you didnt mention in your listing that has great compability and is really easy to use:

            pos: absolute; top:0; bottom:0; left:0; right:0;

            Have a look!
            http://codepen.io/shshaw/full/gEiDt

          • http://getify.me/ getify

            The major caveat there: you have to declare a height for the content element. That automatically limits that technique significantly. The translate() hack is not limited at all. If we’re comparing hacks, translate() is much better, IMO.

          • http://www.nephilistic.com Askhari

            Definitely, no debate about that. But I think it’s a rather elegant solution.

            Oh and btw: I’ve came to advocate the translate method myself after experiencing some annoying Firefox quirks (bugs?) in connection with display:table and absolute positioning. It’s comes with more caveats than I was used to believe.

          • Larry Botha

            display: table; is not the same as using <table> markup.

            Markup, is not CSS. Attributes are not CSS. You’re comparing oranges and apples, and then blaming apples for being oranges.

            If it were called display: [pick a name];, yet elicited the same layout advantages, I’m willing to bet that people would suddenly have a positive perspective simply because it doesn’t have ‘he whose markup name shall not be named’ in its name.

            The issue around tables is excessive and clunky markup. Not the word ‘table’.

            Media blocks are a prime example of how table display properties are beneficial to development, and without using excessive markup. The same goes for clearfixes.

            Not using table display properties would limit us, and for no good reason other than the existence of the word ‘table’. There is no ‘this property is good / bad’ or ‘this property is invalid’. There is only ‘is this property the right tool for the job’.

            I once believed all table display properties were evil – what a relief when I realised that all that CSS is doing is giving us the good things that tables have, and without all the unnecessary cruft!

          • http://getify.me/ getify

            First off, I think using CSS-tables (a *layout structuring* tool) for the precise and limited task of center-positioning of a single element is way way way overkill. When you have to rely on side-effects of some big complex feature, it’s a smell that hacks are abounding. I wrote more about table-overkill-for-centering here: http://blog.getify.com/tables-flex-not-the-centering-youre-looking-for/

            Secondly:

            “If it were called display: [pick a name];, yet elicited the same layout advantages, I’m willing to bet that people would suddenly have a positive perspective…”

            Precisely, if they had chosen a different name, we wouldn’t have this collision of semantics (baggage).

            I explained why I think CSS-tables’ unfortunate naming is part of this doomed downfall here: http://blog.getify.com/html-vs-css-semantics/

            Lastly:

            “The issue around tables is excessive and clunky markup. Not the word ‘table’.”

            False. As I explain in that first link, the problem with tables was never the markup, it was the abuse of a tabular-data-grid-layout mechanism (markup or CSS or whatever, regardless) for doing tasks that are fundamentally NOT tabular-data-grid-layout.

            Since that was the sin then, it’s still the sin today, even if you put lipstick on the pig and pretend that using CSS-tables for non tabluar-grid-layout is somehow defensible. It’s not. It’s still an abuse. We just moved to a different file to place the blame.

  • Phil Tune

    I think a { registration:x y; } property would certainly be in order. I can see it being used in many scenarios, not just positioning. Then use the existing margin thusly: { registration:50% 50%; margin:50% 50%; } for centering, or something like that. Maybe just { left:50%; top:50%; }

  • Chris Perkins

    Thanks for the pointer to the translate() technique, I didn’t know that one.

    I think that a rarely discussed problem is that CSS was meant for primarily text documents, like Microsoft Word. But wasn’t ever intended as a general layout technology (like PageMaker/Quark/Photoshop). And this is why we continue to struggle with things that are fundamentally fairly simple.
    I hate to introduce yet another MIME type into the soup of technologies we web devs need to work with, but I’ve often thought that the layout for a page should not be done in CSS, but in a different format (with a different language). That would also help keep layout out of the semantic flow of the document. So a web page would bind together a layout spec, styling, scripting and the actual content. Probably too late for this idea. Maybe the next time we re-invent everything we’ll get it right.

    • http://getify.me/ getify

      the great thing about standards is that there’s so many to choose from! ;-)

  • Samuel Hodge

    Here is a pure CSS solution for vertically aligning an element without knowing its dimensions and it only requires two wrappers.

    http://codepen.io/Knotix/pen/lLnCe

    • http://getify.me/ getify

      Yeah i addressed hacks like that in the article. The point I’m trying to make here is we need to stop embracing hacks and start pushing for simple and semantic standards that do exactly what we want directly, not as indirect side-effects.

  • http://demosthenes.info/ Dudley Storey

    Nice work, Kyle! Coincidentally, I was working on a CSS centering article just as yours was posted. I’ve covered some of the techniques you mention here, and have added a few more; I’ve also inserted a link to your article for added perspective.

    http://demosthenes.info/blog/723/Six-Ways-of-Centering-With-CSS

    • http://getify.me/ getify

      Nice article. Good job!

  • demarant

    Interesting article, thanks!

    May I ask what’s your definition of “hack”?
    IMO we are surrounded by hacks…..technology is in itself an human hack activity.
    the entire Internet is a hack….because whatever we invent we always come out in new way to use the technique that goes beyond the original goal. Internet was just a military project and specifically never meant for synchrounous communication and streaming…look at it now…we do all sorts of things with it.

    I generally agree with u, that a better css syntax for centering would be nice….but as far as other rather differenr syntax works… I don’t mind….there so many other things that should also be better implemented in CSS.

    It is all about most wanted features and priorities. If you have great ideas plesse do comment to the W3C CSS working group. I believe great ideas and solutions will most often win in the long term.

    • http://getify.me/ getify

      Great question. I wrote a whole follow-up post to this article over on my blog, and in it I specifically address my definition of “hack”.

      http://blog.getify.com/tables-flex-not-the-centering-youre-looking-for/#define-hack

      Basically, I think a hack is using any tool in a way that it’s not semantically designed for, including using tools that are either too complex or too simplistic. When you get your desired outcome as an offshoot or indirect side-effect of some other task, I generally call that a hack.

  • Ti nk

    I would suggest adding horizontalCenter and verticalCenter styles that you would apply to the element you want to center.

    Set it to 0, it would be centered, a negative number would move it left or up from the center, and positive number would move it right or down.

    • http://getify.me/ getify

      that’s an interesting idea. not sure why we’d do it as separate properties rather than just a combined property where the vertical and horizontal values are specificed at once. what do you think?

      maybe just a `center:0px 0px` rule for real centering, and then `center:-10px 25px` for 10px left and 25px down from the center?

      • Ti nk

        I pulled horizontalCenter and verticalCenter directly from how we would center a component in Flex.

        If the 2 where combined, would I still be able to specify one without specifying the other?

        For instance inFlex i could do (psuedo code)

        • http://getify.me/ getify

          the precedent in CSS is to provide overloading of the property setting. So, for instance, you can set both by passing two values, or set both to the same value by passing just one value. As for only setting one and not the other, that seems a lesser use-case. Sometimes CSS has provided specific setters (like `border-bottom-radius`) in addition to the short-hand combinations. But I rarely like working with them.

          What I would see is that you would “always” want to set both the vertical and horizontal settings, even if one of them was a placeholder like “default” or “none” or something like that. That seems the simplest, and is only a little bit more verbose in the lesser-common cases.

          • Ti nk

            My experience is that I often don’t want to set both, I just want something centered horizontal and not vertically or vice versa, using the other properties availble to set the position on the other axis. That said the use of ‘none’ would be a decent workaround.

  • Sindre Moen

    For things that are positioned “absolute”, and that you know the height of, you could use a clever combination of top and margin-top. Say it’s an absolutely positioned with a height of 200px. Specifying top: 50% and margin-top: -100px (negative value of half the height), this keeps it vertically centered in a container of unknown height. You can even scale the container height – the content will remain centered. ;-)

    • http://getify.me/ getify

      The translate() “hack” mentioned above does the same thing as you’re suggesting, but you get to use “-50%” instead of “-100px”, which is more robust because you don’t have to adjust it at all if the content itself changes size.

      • Sindre Moen

        Yes, this is true, but translate is not supported by older versions of IE and stuff, so I thought I’d throw it out there. :-)

  • David

    you can do what facebook does: .box { display: inline-block; vertical-align: center } .container {height: 50px;} This is vertically centered This might require a bit of finagling but if you look up the people who’ve “liked” something in their little modal, each element has this empty inline-block styling attached to it. It feels somewhat hacky but it works.

    • http://getify.me/ getify

      Hacks suck. I want us to move beyond hacks. :)

  • rpearce00

    What about this solution which, instead of using the ::before pseudo-selector, uses an empty element to vertically center it’s sister content? 3 elements, 3 classes, cross-browser, vertically centered. http://codepen.io/anon/pen/vHjKu

  • http://dmitriid.com/ Dmitrii ‘Mamut’ Dimandt

    This is why w3c whould be killed with fire. They create monstrous specs that solve none of the problems they say these specs would, and which are almost impossible to implement correctly

    • http://getify.me/ getify

      I too am frustrated, but I have a somewhat more optimistic view, if more “grass roots specs” efforts like what I’m trying to do with these articles can eventually inform the specs of what real developers actually want.

  • http://www.mathewporter.co.uk/ Mathew Porter

    Nice article, its a shame that there isnt a full proof solution in the markup yet that would work for elements that we dont have a set height and width on.

    • http://getify.me/ getify

      the translate() hack works pretty well even if the content changes dimensions. the parent doesn’t have to be automatically sized, but it can’t just be shrink-wrapped around the content you’re trying to center, so it has to get size some other way, like auto stretching to some container it’s in, etc.

  • Pedro Figas

    FYI, if element to center vertically has dynamic height, use an invisible midliner

    .midliner {
    height : 100%;
    width : 0px;
    font-size : 1px;
    vertical-align : middle;
    display : inline-block;
    }

    .the_element_to_center_vertically {
    display : inline-block;
    height : auto;
    }

  • Pedro Figas

    If I am not mistaken IE8 and under don’t support transforms, right? Anyway, IE8 will slowly fade away now… I hope… man I hate IE… Anyway thanks for sharing a great page :)

  • daym

    Good article.

    However note that translate() hack is not bulletproof – I found out it messes with event.layerX/Y (e.g. onclick), the values become arbitrary and can be negative. Have you ever seen negative layerX? Negative values are ‘outside’ the element, hence unclickable and can raise funny errors.

    Another bug you can get from translate() is with draggable=true elements – if your hack-centered element contains draggable child element, drag ghost can become cropped or invisible.

    Try this:

    Some text here.

    Drag the red div – ghost is offset to the right-bottom and is grey and empty, like it was cut out from the big div.

    Now delete the translates and drag again – ghost is red and has text, like it should.

  • Jeff

    I originally thought this article was to be about vertical centering. Something like making your initial Hello World example and then turning it 180-degrees.

    How would that be done?

  • Dev.

    thank you posting the translate 50-50 one. It is what I was looking for!!
    Regarding the future of centering I would like a one-fit-all solution to end this madness FFS!

  • John Masters

    DISPLAY seems so logical…
    I think that within an element, you should be able to use the ‘display’ tag in a manner like this:

    - content-

  • Jnana Rana

    Thanks you very much for the article it helped me a lot

  • http://www.lucagrandicelli.co.uk Luca Grandicelli

    Flexbox is the solution. Straight and simple.