Absolute Horizontal And Vertical Centering In CSS

Advertisement

We’ve all seen margin: 0 auto; for horizontal centering, but margin: auto; has refused to work for vertical centering… until now! But actually (spoiler alert!) absolute centering only requires a declared height*1 and these styles:

.Absolute-Center {
  margin: auto;
  position: absolute;
  top: 0; left: 0; bottom: 0; right: 0;
}

I’m not the pioneer of this method (yet I have dared to name it Absolute Centering), and it may even be a common technique, however, most vertical centering articles never mention it and I had never seen it until I dug through the comments section of a particular article2.

There, Simon3 linked to this jsFiddle4 that blew every other method out of the water (the same method was also mentioned by Priit5 in the comments). Researching further, I had to use very specific keywords to find some6 other7 sources8 for this method.

Having never used this technique before, I put it to the test and discovered how incredible Absolute Centering really is.

Leave a comment on CodePen129, Smashing Magazine10, or message @shshaw11 on Twitter if you have any additional features or suggestions.

Find additional demos, a comparison table, and more on CodePen129.

Advantages: Link

  • Cross-browser (including IE8-10)
  • No special markup, minimal styles
  • Responsive with percentages and min-/max-
  • Use one class to center any content
  • Centered regardless of padding (without box-sizing!)
  • Blocks can easily be resized
  • Works great on images

Caveats: Link

  • Height must be declared (see Variable Height13)
  • Recommend setting overflow: auto to prevent content spillover (see Overflow14)
  • Doesn’t work on Windows Phone

Browser Compatibility: Link

Chrome, Firefox, Safari, Mobile Safari, IE8-10.
Absolute Centering was tested and works flawlessly in the latest versions of Chrome, Firefox, Safari, Mobile Safari, and even IE8-10.

Explanation Link

After researching specs and documentation, this is my understanding of how Absolute Centering works:

  1. In the normal content flow15, margin: auto; equals ‘0’ for the top and bottom.
    W3.org16: If ‘margin-top’, or ‘margin-bottom’ are ‘auto’, their used value is 0.
  2. position: absolute; breaks the block out of the typical content flow, rendering the rest of the content as if that block weren’t there.
    Developer.mozilla.org17: …an element that is positioned absolutely is taken out of the flow and thus takes up no space
  3. Setting top: 0; left: 0; bottom: 0; right: 0; gives the browser a new bounding box for the block. At this point the block will fill all available space in its offset parent, which is the body or position: relative; container. Developer.mozilla.org1918: For absolutely positioned elements, the top, right, bottom, and left properties specify offsets from the edge of the element’s containing block (what the element is positioned relative to).
  4. Giving the block a width or a height prevents the block from taking up all available space and forces the browser to calculate margin: auto based on the new bounding box. Developer.mozilla.org1918: The margin of the [absolutely positioned] element is then positioned inside these offsets.
  5. Since the block is absolutely positioned and therefore out of the normal flow, the browser gives equal values to margin-top and margin-bottom centering the element in the bounds set earlier.
    W3.org20: If none of the three [top, bottom, height] are ‘auto’: If both ‘margin-top’ and ‘margin-bottom’ are ‘auto’, solve the equation under the extra constraint that the two margins get equal values. AKA: center the block vertically

Absolute Centering appears to be the intended use for margin: auto; based on the spec and should therefore work in every standards compliant browser.

TL;DR: Absolutely positioned elements aren’t rendered in the normal flow, so margin: auto; centers vertically within the bounds set by top: 0; left: 0; bottom: 0; right: 0;.

Within Container Link

.Center-Container {
  position: relative;
}

.Absolute-Center {
  width: 50%;
  height: 50%;
  overflow: auto;
  margin: auto;
  position: absolute;
  top: 0; left: 0; bottom: 0; right: 0;
}

With Absolute Centering, you can place your content block inside of a position: relative container to align the block within the container!

The rest of the demos will assume these styles are already included and will provide add-on classes to implement various features.

Absolute Center,
Within Container.

This box is absolutely centered, horizontally and vertically, within its container using
position: relative

Within Viewport Link

.Absolute-Center.is-Fixed {
  position: fixed;
  z-index: 999;
}

Want the content block centered in the viewport? Set it to position: fixed and give it a high z-index, like the modal on this page.

  • Mobile Safari: The content block will be centered vertically in the whole document, not the viewport, if it is not within a position: relative container.

See the Modal Demo page.21

Offsets Link

.Absolute-Center.is-Right {
  left: auto; right: 20px;
  text-align: right;
}

.Absolute-Center.is-Left {
  right: auto; left: 20px;
  text-align: left;
}

If you have a fixed header or need to add other offsets, simply add it in your content block’s styles like top: 70px;. As long as margin: auto; is declared, the content block will be vertically centered within the bounds you declare with top left bottom and right.

You can also stick your content block to the right or left while keeping it vertically centered, using right: 0; left: auto; to stick to the right or left: 0; right: auto; to stick to the left.

Vertical Center,
Align Right.

This box is absolutely centered vertically within its container, but stuck to the right with
right: 0; left: auto;

Footnotes Link

  1. 1 http://www.smashingmagazine.com/2013/08/09/absolute-horizontal-vertical-centering-css/2#Height
  2. 2 http://designshack.net/articles/css/how-to-center-anything-with-css
  3. 3 http://designshack.net/articles/css/how-to-center-anything-with-css/#comment-684580538
  4. 4 http://jsfiddle.net/mBBJM/1/
  5. 5 http://designshack.net/articles/css/how-to-center-anything-with-css/#comment-684580409
  6. 6 http://www.vanseodesign.com/css/vertical-centering/
  7. 7 http://www.student.oulu.fi/~laurirai/www/css/middle/
  8. 8 http://blog.themeforest.net/tutorials/vertical-centering-with-css/
  9. 9 http://codepen.io/shshaw/details/gEiDt
  10. 10 http://www.smashingmagazine.com/2013/08/09/absolute-horizontal-vertical-centering-css/#comments
  11. 11 http://twitter.com/shshaw
  12. 12 http://codepen.io/shshaw/details/gEiDt
  13. 13 http://www.smashingmagazine.com/2013/08/09/absolute-horizontal-vertical-centering-css/2#Height
  14. 14 #Overflow
  15. 15 http://taligarsiel.com/Projects/howbrowserswork1.htm#Layout
  16. 16 http://www.w3.org/TR/CSS2/visudet.html#normal-block
  17. 17 https://developer.mozilla.org/en-US/docs/Web/CSS/position#Absolute_positioning
  18. 18 https://developer.mozilla.org/en-US/docs/Web/CSS/position#Notes
  19. 19 https://developer.mozilla.org/en-US/docs/Web/CSS/position#Notes
  20. 20 http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-height
  21. 21 http://s.codepen.io/shshaw/fulldetails/gEiDt#Fixed

↑ Back to top Tweet itShare on Facebook

A passionate front-end developer who cares about CSS, JavaScript and keeping code clean and nifty.

Advertisement
  1. 1

    This is a mystic quest for lot’s of webdesigner !
    Thanks for sharing those informations.

    5
  2. 3

    Guides like this saves a lot of time. Unfortunately CSS is not as intuitive as it should be.

    5
  3. 4

    Genius technique thanks :-)

    1
  4. 5

    Kim Andre Ottesen

    August 9, 2013 11:42 pm

    Great and flexible technique I’ve used quite a lot, e.g. when combined with Flexslider to create a sleek centered gallery.

    -1
  5. 6

    Very useful article! My favorite technique is how Magnific Popup centers content, as its kept responsive and scrollbar is triggered when height is bigger then window, there was an article on SM – http://coding.smashingmagazine.com/2013/05/02/truly-responsive-lightbox/

    1
  6. 7

    I was overwhelmed with the urge to try this out as soon as I saw it. Ten minutes later, I have this: http://instadesign.co.uk/absolutcenter/

    Thanks so much, I shall not be forgetting this!

    4
    • 8

      It’s not perfect on chrome… Try to change browsers height to smaller than the content. You will see that TOP of the page is getting CROPPED!

      0
    • 9

      I have to admit it took me a couple of seconds to understand it… :(

      0
  7. 10

    Just use a table, idiot.

    -31
    • 11

      LOL. I haven’t thought of that method since 2001. It. Just. Makes. Sense.

      0
      • 12

        Display:table; height:100% (and parents with height:100%) is the solution: I’m not going to argue with MDO from Bootstrap on this one. (check the examples: Cover)

        -2
  8. 13

    Mark Petherbridge

    August 10, 2013 12:03 am

    Thank you for this wonderful and concise solution to all my hacky code. I do believe that you are about to save me a lot of time, and for that kudos.

    0
  9. 14

    Woaah! This solves a lot of problems for me. I used to do all sorts of tricks to get it right, including negative margins, but this is just perfect! I don’t use flexbox yet because of browser compatibility and display: table introduces a whole lot of problems in Firefox and IE for images (you can’t use min- and max-).

    0
  10. 15

    This gives so much relief…thanks for sharing!

    0
  11. 16

    Great resource, thanks for sharing. Alignments are always a nightmare! :D

    0
  12. 17

    I wonder what would be the best technique right now, to place vertically and horizontally centered text on image thumbnails (on hover) in responsive layouts, since we normally only set width on those elements, to fit the grid.

    0
  13. 18

    It’s smashing!thank you

    0
  14. 19

    That’s what browsers use to center standalone images.. since the dawn of time. Never looked at their code? :)

    0
  15. 20

    The first version DOES work on Windows Phone, at least WP8+IE10. It may not work in WP7/7.5+IE9 but browser share of that is getting smaller by the minute and was not high to begin with. But nice work!

    1
    • 21

      Thanks for the info! I need to get a BrowserStack account so I can try Absolute Centering out in all of the mobile browsers :-)

      0
  16. 22

    Irina Petculescu

    August 10, 2013 3:14 am

    great roundup, thanx

    0
  17. 23

    But no height: auto for divs, which is where it would REALLY be interesting and helfpul. It’s a good technique, no doubt, but it rarely comes to help. I’ve been doing top: 50%; height: X; margin-top: X/2; for the most part, and it works.

    For height: auto, I’ve been doing jquery events to change the margin-top on render and on window resize, and it works, but it requires javascript, which sucks.

    0
    • 24

      If you need height: auto, read over the Variable Height section for some tips, or you can try one of the alternative methods, like Table-Cell that will get it done without needing Javascript!

      0
  18. 25

    Thank-you! Goodbye, negative margins!

    0
  19. 26

    This is neat, but isn’t going to replace the table-cell method for me. I’ve been using table cell for a long time and have the markup/CSS snippets in my toolbox, so the one caveat isn’t concerning enough to trade for cross browser performance. Maybe I’m just not adventurous enough…

    0
  20. 27

    Very useful for all designer/developer. Thanks for sharing it.

    0
  21. 28

    Very useful….
    Thanks for this…… :)

    0
  22. 29

    Great article! These type of layout things can be troublesome when you are first getting started with web development. I was reminded of this recently talking to a junior web designer who just started and was expressing his frustration at getting things lined up right. I made sure to share this with him. Thanks!

    0
  23. 30

    Interesting technique. Another technique that is as versatile and effective, but IMHO more idiomatic, is the one exemplified here: http://jsfiddle.net/uy64k/4/ . This technique is a variation of the vertical-align/line-height technique (which to me, is the idiomatic way to achieve vertical alignment) that takes advantage of inline-block to allow for generic content.

    The only drawback, so far as I can tell, is that it inhibits line-height and font-size inheritance.

    0
  24. 33

    Thierry Koblentz

    August 10, 2013 1:00 pm

    There is another way to do this:

    http://jsfiddle.net/thierrykoblentz/cXwZn/3/embedded/result/

    The big advantage of this solution is that it does not require to style the box with explicit dimensions (width or height).

    0
  25. 35

    Excellent post. I saw this on Codepen and I am glad that this is shared.

    0
  26. 36

    I’d love to see a little JavaScript test that checks the browser to see if it’s capable of this method. Maybe a Modernizr-style test that puts either .shaw or .no-shaw on the HTML element.

    0
  27. 39

    This is such an easy way I was looking for so long. Thanks for sharing!

    Regards.

    0
  28. 40

    Interesting, cool and simple.

    *But*: why does this work? Should this really happen according to the CSS specification or is that just emergent behaviour that happens to be the same across all (most) browsers?

    0
    • 41

      Thierry Koblentz

      August 11, 2013 9:04 am

      Check this: http://www.css-101.org/block-level-elements/index.php

      Three of the seven properties can be set to auto:
      —————————————————————————-

      * margin-left
      * width
      * margin-right

      For replaced elements, a value of auto on ‘width’ is replaced by the intrinsic width, so for them there can only be two auto values.

      If exactly one of margin-left, width, margin-right is auto, the UA will assign that property a value that will make the sum of the seven equal to the parent’s width.

      If none of the properties are auto, the value of ‘margin-right’ will be assigned ‘auto’.

      If more than one of the three is auto, and one of them is ‘width’, then the others (‘margin-left’ and/or ‘margin-right’) will be set to zero and ‘width’ will get the value needed to make the sum of the seven equal to the parent’s width.

      Otherwise, if both margin-left and margin-right are auto, they will be set to equal values. This will center the element inside its parent.

      If auto is set as the value for one of the seven properties in an element that is inline or floating, it will be treated as if it were set to zero.

      0
      • 42

        Sorry, I should have been more specific. I meant vertical centering, which is achieved through

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

        In conjunction with

          margin: auto;
        

        As I said, it’s interesting that this seems to work, but why?

        0
        • 43

          Fritz,
          Here is my understanding of how this works:

          [1.] In the normal content flow ( http://taligarsiel.com/Projects/howbrowserswork1.htm#Layout ), “margin: auto;” doesn’t work on the top and bottom due to margin collapsing ( https://developer.mozilla.org/en-US/docs/Web/CSS/margin_collapsing and http://www.w3.org/TR/CSS2/visudet.html#normal-block “If ‘margin-top’, or ‘margin-bottom’ are ‘auto’, their used value is 0.” ).

          [2.] “position: absolute;” breaks the block out of the typical content flow, rendering the rest of the content as if that block weren’t there ( https://developer.mozilla.org/en-US/docs/Web/CSS/position#Absolute_positioning “…an element that is positioned absolutely is taken out of the flow and thus takes up no space”).

          [3.] Setting “top: 0; left: 0; bottom: 0; right: 0;” gives the browser a new bounding box for the block. At this point the block will fill all available space in its offset parent, which is the body or “position: relative;” container. ( https://developer.mozilla.org/en-US/docs/Web/CSS/position#Notes “For absolutely positioned elements, the top, right, bottom, and left properties specify offsets from the edge of the element’s containing block (what the element is positioned relative to). The margin of the [absolutely positioned] element is then positioned inside these offsets.” )

          [4.] Giving the block a width or a height prevents the block from taking up all available space and forces the browser to calculate the “auto” margin based on the new bounding box.

          [5.] Since the block is absolutely positioned and therefore out of the normal flow, margin collapsing doesn’t apply and thus the block is centered vertically. ( https://developer.mozilla.org/en-US/docs/Web/CSS/position#Values “Absolutely positioned boxes can have margins, they do not collapse with any other margins.” and most importantly… http://www.w3.org/TR/CSS2/visudet.html#abs-replaced-height “4. If at this point both ‘margin-top’ and ‘margin-bottom’ are still ‘auto’, solve the equation under the extra constraint that the two margins must get equal values.” AKA: center the block vertically )

          Whew. As best I can tell, this method is actually the intended use for “margin: auto;” based on the spec and will therefore work in every standards compliant browser!

          TL;DR: Absolutely positioned elements aren’t rendered in the normal flow, so “margin: auto;” centers vertically within the bounds set by “top: 0; left: 0; bottom: 0; right: 0;”.

          0
        • 44

          Thierry Koblentz

          August 14, 2013 8:11 am

          @Fritz For the exact same reason as it works vertically – as explained on http://css-101.org.

          The browser uses “auto” to distribute the available space. The “margin box” is horizontally/vertically stretched and the box itself has an explicit width and height, so whatever is around the “border box” is the margin edge (margins are the available space), if opposite margins are both set to auto, then that value is split between the 2 opposite margins. Nothing magic, it is just the spec…

          As a side note, this has nothing to do with margin collapsing.

          0
          • 45

            Thierry,

            Looks like you’re right; margin collapsing isn’t exactly at play here. I may have misinterpreting the spec ( http://www.w3.org/TR/CSS2/visudet.html#normal-block “If ‘margin-top’, or ‘margin-bottom’ are ‘auto’, their used value is 0.” ) as margin collapsing, but it looks like it’s simpler than that. Thanks!

            0
          • 46

            I am not sure I can follow. css-101 even states that

            “Boxes with explicit dimensions do not stretch nor shrink.”
            ( http://www.css-101.org/absolute-positioning/03.php )

            As far as I understood it, defining a width and height plus defining an absolute position and top/left/right/bottom:0 is ambiguous (and according to css-101, only width and height will be considered and top/left/right/bottom is ignored).

            0
  29. 47

    Great technique. It’s hard to believe something like this isn’t common knowledge already.

    0
  30. 49

    Ive been trying to find this out for ages! Thanks a lot Thierry…

    0
  31. 50

    Great article!
    You made my day. Great work, thanks!!! :)

    0
  32. 51

    Hi, that worked; thanks.

    0
  33. 52

    Here is a great technique to absolutely center an element of variable dimensions:

    http://iclanzan.com/centering-variable-height-elements-both-horizontally-and-vertically-in-css/

    0
    • 53
      • 54

        Thierry Koblentz

        August 13, 2013 8:15 pm

        I copied/pasted your code without realizing that you’re using :after instead of :before (hence the letter-spacing not making the box drop). This is a smarter way / much safer than using :before. Nice find/improvement!

        0
        • 55

          Yes, thanks! I ran in to an issue where the psuedo element was pushing the content block down when a width wasn’t declared on the center block and the content was wider than the container.

          At least with :after, the content block will be pushed to the top if that happens. Using :before caused the content to be pushed down 100% and possibly even get cut off if the container has overflow:hidden!

          0
  34. 56

    Also done it this way:

    rule {
       width: 40;
       height:40%;
       position:absolute;
       left:50%;
       top:50%;
       margin:-20% 0 0 -20%;
    }
    

    negative left positioning against 1/2 of the total width

    0
  35. 57

    A great wrapup of solutions for a problem that has plagued many a web designer. Great article!

    0
  36. 58

    display: inline-block and pseudo-element method is also worth attention
    Fast fiddle: http://jsfiddle.net/7j5Da/

    Gumby framework uses this method. It also works for elements with unknown height.

    0
  37. 60

    Diego de Oliveira

    August 12, 2013 9:10 am

    Dude, I can’t believe… I was just searching a way to do a horizontal centered block with fluid size, and came here to see the latest news… and found this article! Just in time! Thank you!

    0
  38. 61

    This is awesome. Thank you !!

    0
  39. 62

    I know this solution seems like magic to everyone, but it’s not a magic silver bullet, because (as noted), the major caveat is that you have to set the height on the content element. If you have to set the height, then this technique is really no better than a whole bunch of other hacks (some noted here) like the negative margins, because if you have a fixed height, calculating what half the height is isn’t so bad.

    But it’s all those cases out there where you need vertical centering of a flexible height content box that we all really struggle with. When you are in that scenario, the translate(-50%,-50%) hack is more robust because it automatically calculates “half the height” for you regardless of how tall your content stretches.

    BUT, and this is the most important point I’d like to make, every single thing presented here, and in every other article like it over the years, is all about hacks to get CSS to approximate centering positioning.

    No, flexbox and tables are not the answer, they are bringing a sledgehammer to insert a pushpin. They are for layout structure, not precise positioning tasks. I explain why here: http://blog.getify.com/tables-flex-not-the-centering-youre-looking-for/

    What we finally need is a real solution that’s JUST for positioning. I tried to write up a bunch of these concerns in this post:

    http://html5hub.com/centering-all-the-directions/

    Unfortunately, a lot of people missed the real point there, where I submitted a simple soft-proposal for a better standard way of doing centering-positioning.

    0
    • 63

      Nice suggestion. As a beginner to CSS, i’d been led to believe that there *couldn’t* be a solution to vertical alignment, not that there just WASN’T a solution as yet :)

      0
  40. 64

    i’ve made this using jquery, best solution for me. Getting divs width&height and then get the window width&height and when the document is ready or resized, elements are positioned via .css property

    0
  41. 65

    Incredible that such tricks are needed, like spaggety code for a commodore 64, times have not changed in 30 years.

    0
  42. 66

    This is a great technique. It’s nice to have all of my center align options here, in one place.

    By the way, the “table comparison” link, near the end of the article, is broken. Is there any way to get that working? I’d like to check out the comparison chart.

    Thanks!

    0
  43. 68

    Hi Stephen,

    While the technique is useful the label absolute-center is not. Nothing in your class is about centering – how about:

    .Absolute-Fit-to-First-Relative-Parent-or-Body {
      margin: auto;  position: absolute;  top: 0; left: 0; bottom: 0; right: 0;
    }

    More explaining – less branding :)

    0
    • 69

      Hah. You’re right that the class on just that snippet of code isn’t completely semantic. However, the class name does make more sense on the first example code.

      Do you have any other suggestions for a more generic class name for the bare code? .Absolute-Fit-to-First-Relative-Parent-or-Body just doesn’t have quite the same ring to it! :-)

      0
      • 70

        I know this is a year old now, but… isn’t that what absolute means? Absolute to the first positioned parent?

        0
        • 71

          Essentially. Absolute positions the box within its containing block. ( http://www.w3.org/TR/CSS2/visuren.html#propdef-position )

          Jakob’s (sarcastic) remark was that the class name “.absolute-center” isn’t semantic, in that these properties alone don’t center the element, but rather cause the box to fill the containing block. A more semantic class would be something like `.text-center { text-align: center; }`

          While `.absolute-center` may not be strictly semantic, the intention of adding the class is very clear, in my opinion. Depending on your usage of the class, you could add some default widths and heights to ensure that adding the class will make the element appear centered, but since this article was about the technique, I made the class itself as universal as possible with the fewest necessary styles included.

          0
  44. 72

    Thank you so much for this awesome technique really that would be really helpful for me… Thank once again.. Cheers :)

    0
  45. 73

    Horizontal and vertical centering is a NP-complete problem!

    0
  46. 74

    Bookmarked! Thanks for this nice tool.

    0
  47. 75

    nice :)

    0
  48. 76

    I just wanted to report a Problem/BUG that’s related to Firefox/Chrome and the “Within Container” method here.
    If you want to get the “top” value in Javascript from the inner DIV, Firefox will display a calculated value while Chrome will return top: 0.

    Firebug also displays a different value than the webkit dev tool.

    This is an important fact that will break Javascript Animations and the likes.

    Here’s a fiddle:
    http://jsfiddle.net/kDAqE/4/

    EDIT:

    Example: If the top offset is 50px it will be like this:

    Firefox: top: 50px, margin-top: 0
    Chrome: top: 0px, margin-top: 50px

    0
    • 77

      Interesting bug. Chrome is returning the correct value (0) for .css("top"), since that is the declared value for top. Firefox however returns the top value plus the calculated margin.

      To get a consistent number cross-browser, use $('.inner').offset().top instead of position().top or trying to fetch the CSS top value. offset().top is the better method of detecting the distance from its offset parent, not just whatever the declared top value is. I also tested this with the inline-block method and table method, and offset().top returned the correct results in Firefox and Chrome.

      That said, you may run into some issues with built in animations or other plugins code if they use position().top or the declared top value, but you should be able to adapt them to use offset().top instead.

      0
      • 78

        Ahh yes the offset().top – thanks for that.
        I still think it should be pointed out in the article that FF will add the offset-value to the margin-top property. Other browsers i’ve tested (IE8 IE9 IE10 Chrome) will use the top property.

        0
  49. 79

    I like this. Awsome !!

    BUT , is there any method to implement the same in IE7 too. using css or jquery or both?

    0
  50. 81

    Oh Stephen! What a nice trick!! You should have discovered it years ago :P
    There is a little thing I can’t understand, when the container is smallest than the content, the horizontal centering is not working. Can you imagine a fix for that? Cheers.

    http://jsfiddle.net/marquex/ru2Mc/

    0

↑ Back to top