6 Methods For Vertical Centering With CSS

Centering elements vertically with css is something that often gives designers trouble. There are however a variety of methods for vertical centering and each is fairly easy to use. Today I want to present 6 of those methods.

I’ve usually skipped over the topic of vertical centering, since there are some good posts already out there that are easy enough to find, but recently Bikram commented requesting a tutorial on vertically centering so I thought why not.

You can view demos of each of the methods below by clicking here. Clicking the images above each section will also take you to that specific demo.

Let’s start by first talking about something that doesn’t work as many expect. Understanding why vertical-align doesn’t always work will help us better understand vertical centering in general.

abstract photograph of vertical light

Vertical-Align

Horizontal centering with css is rather easy. When the element to be centered is an inline element we use text-align center on its parent. When the element is a block level element we give it a width and set the left and right margins to a value of auto.

With text-align: center in mind, most people look first to vertical-align in order to center things vertically. It seems logical and I know it was my first choice. If you’ve come from table based layout you likely used the valign attribute, which would also lead you to believe vertical-align is the way to go.

However valign only worked on table cells. Vertical-align is similar. It also applies to table cells and it works with some inline elements.

The values for vertical-align have meaning with respect to a parent inline element.

  • With a line of text the values are relative to the line-height.
  • With a table cell the values are relative to the table-height-algorithm, which usually means the height of the row.

Unfortunately vertical-align doesn’t apply to block-level elements like a paragraph inside a div, which is where most of us figure out it isn’t the be all solution to vertical centering.

All is not lost though, as we have other methods for centering block level elements and we can still use vertical-align where appropriate. Which method you choose will depend on what you’re trying to center relative to its container element.

line height demo

Line-Height Method

This method will work when you want to vertically center a single line of text. All we need to do is set a line-height on the element containing the text larger than its font-size.

By default equal space will be given above and below the text and so the text will sit in the vertical center.

Most tutorials will also set the height on the element with the same value given to the line-height. I don’t think setting the height is necessary, but if line-height alone doesn’t work for you setting the height of the element will likely be the solution.

html

1
2
3
<div id="parent">
    <div id="child">Text here</div>
</div>

css

1
2
3
#child {
    line-height: 200px;
}

The above works in all browsers, however it will only work for a single line of text. If your text could wrap to a 2nd line you need to use a different method. The value of 200px above is arbitrary. You can use any value you want as long as its larger than the font-size that’s been set.

Added: As Jeff pointed out in the comments below, there’s one small got’cha with this method in that you have to be careful when using the shortcut for the font property. This method relies on you setting the line-height as a value greater than the font-size. When you use the font shortcut any property you don’t specifically set gets set to its default value. With line-height that default is 1. If you use the font shortcut, just make sure to explicitly set the line-height inside.

Centering an Image with Line-Height

What if the content you want centered is an image? Will this method work? The answer is yes with one additional line of css.

html

1
2
3
<div id="parent">
    <img src="image.png" alt="" />
</div>

css

1
2
3
4
5
6
7
#parent {
    line-height: 200px;
}

#parent img {
    vertical-align: middle;
}

You set the line-height as we did above (It’ll need to be greater than the height of the image) and then set vertical-align: middle on the image.

table cell demo

CSS Table Method

Above I mentioned that vertical-align applies to table cells which leads us to this method. We’ll display our elements as table and table cell and then use the vertical-align property to center the content.

Note: CSS tables are not the same as html tables.

html

1
2
3
<div id="parent">
    <div id="child">Content here</div>
</div>

css

1
2
3
4
5
6
#parent {display: table;}

#child {
    display: table-cell;
    vertical-align: middle;
}

We set the parent div to display as a table and the child div to display as a table-cell. We can then use vertical-align on the child div and set its value to middle. Anything inside this child div will be vertically centered.

Unlike the method above the content can be dynamic as the div will grow with what’s placed inside. The downside of this method is it doesn’t work in older versions of IE, though there is a fix, which is to add display: inline-block to the child element.

1
2
3
#child {
    display: inline-block;
}

absolute positioning and negative margin demo

Absolute Positioning and Negative Margin

This method works for block level elements and also works in all browsers. It does require that we set the height of the element we want to center.

In the code below I’m centering the child both vertically and horizontally using this method.

html

1
2
3
<div id="parent">
    <div id="child">Content here</div>
</div>

css

1
2
3
4
5
6
7
8
9
10
#parent {position: relative;}

#child {
    position: absolute;
    top: 50%;
    left: 50%;
    height: 30%;
    width: 50%;
    margin: -15% 0 0 -25%;
}

We begin by positioning both parent and child divs. Next we set the top and left values of the child to be 50% each, which would be the center of the parent. However this sets the top left corner to be in the center so we’re not done.

We need to move the child up (by half its height) and to the left (by half its width) so its center is what sits in the center of the parent element. This is why we need to know the height (and here the width) of the child element.

To do that we give the element a negative top and left margin equal to half its height and width.

Unlike the first 2 methods this one is meant for block level elements. It does work in all browsers, however the content can outgrow its container in which case it will disappear visually. It’ll work best when you know the heights and widths of the elements.

absolute positioning and vertical stretching demo

Absolute Positioning and Stretching

As with the method above this one begins by setting positioning on the parent and child elements as relative and absolute respectively. From there things differ.

In the code below I’ve once again used this method to center the child both horizontally and vertically, though you can use the method for vertical centering only.

html

1
2
3
<div id="parent">
    <div id="child">Content here</div>
</div>

css

1
2
3
4
5
6
7
8
9
10
11
12
#parent {position: relative;}

#child {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    width: 50%;
    height: 30%;
    margin: auto;
}

The idea with this method is to try to get the child element to stretch to all 4 edges by setting the top, bottom, right, and left vales to 0. Because our child element is smaller than our parent elements it can’t reach all 4 edges.

Setting auto as the margin on all 4 sides however causes opposite margins to be equal and displays our child div in the center of the parent div.

Unfortunately the above won’t work in IE7 and below and like the previous method the content inside the child div can grow too large causing it to be hidden.

vertical centering with padding demo

Equal Top and Bottom Padding

In the method above we allowed the browser to automatically set the margins of the child element so they would be equal. In this method we’ll do something similar and explicitly set the top and bottom padding of the parent to be equal.

html

1
2
3
<div id="parent">
    <div id="child">Content here</div>
</div>

css

1
2
3
4
5
6
7
#parent {
    padding: 5% 0;
}

#child {
    padding: 10% 0;
}

In the css above I’ve set top and bottom paddings on both elements. Setting it on the child will make sure the contents in the child will be vertically centered and setting it on the parent ensures the entire child is centered within the parent.

I’m using relative measurements to allow each div to grow dynamically. If one of the elements or its content needs to be set with an absolute measurement then you’ll need to do some math to make sure things add up.

For example if the parent was 400px in height and the child 100px in height we’d need 150px of padding on both the top and bottom.

150 + 150 + 100 = 400

Using % could throw things off in this case unless our % values corresponded to exactly 150px.

This method works anywhere. The downside is that depending on the specifics of your project you may need to do a little math. However if you’re falling in line with the idea of developing flexible layouts where your measurements are all relative you can avoid the math.

Note: This method works by setting paddings on the outer elements. You can flip things and instead set equal margins on the inner elements. I tend to use padding, but I’ve also used margins with success. Which you choose would depend on the specifics of your project.

vertical centering with floater div demo

Floater Div

This last method requires an empty div which is floated and used to control where our child element sits in the document flow. Notice the floater div comes before our child div in the html below.

html

1
2
3
4
<div id="parent">
    <div id="floater"></div>
    <div id="child">Content here</div>
</div>

css

1
2
3
4
5
6
7
8
9
10
11
12
13
#parent {height: 250px;}

#floater {
    float: left;
    height: 50%;
    width: 100%;
    margin-bottom: -50px;
}

#child {
    clear: both;
    height: 100px;
}

We float the empty div to the left (or right) and give it a height of 50% of the parent div. That causes it to fill up the entire upper half of the parent element.

Because this div is floated it’s removed from the normal document flow so we need to clear the child element. Here I’ve used clear: both, but you just need to clear in the same direction you floated the empty floater div.

The top edge of the child div should now be immediately below the bottom edge of the floater div. We need to bring the child element up by an amount equal to half its height and to do so we set a negative margin-bottom on the floater div.

This method also works across browsers. The downside is that it requires an empty div and that you know the height of the child element.

Additional Resources

In the sections above I linked to articles specific to each method. Below are some resources that cover more than a single method for centering.

verticle fence posts

Summary

None of the methods above is complicated and I’m sure if you use each once or twice it’ll be easy to use again.

The difficultly if there is one is that none of the methods above is perfect for all occasions. The trick is to understand several of the above and use each appropriately.

Some of the methods work better for inline elements and others work better for block level elements. Some might work better with your preference for developing a layout and some don’t work in older versions of a certain browser we all know well.

Rarely do I vertically center elements in a design. When I do the methods I tend to use are the line-height method and the equal padding method. One or the other has always worked for my needs.

If neither worked I would reach for either the positioning or floater methods and save the table cell method as a last resort. In time we’ll be able to use the css3 flexible box layout module and forget about the methods above, but for now browser support isn’t quite there.

Do you use any of the above methods or do you use a different method I didn’t mention? Is there a vertical centering issue that none of the methods here address?

Download a free sample from my book, Design Fundamentals.

115 comments

  1. A very good article, and one I am sure I will come back to next time I am stuck (I do know them but you know what its like when you get stuck and forget everything!)… but I still cannot stand the way vertically aligning text and images is done. I hope it is fixed in 3 or 3.1!

    • Thanks Shane. I’ll come back to it too. Part of why I wrote it was to remind myself of these methods when I forget the details. :)

      In time we’ll be able to use the flexible box model, but the support for it isn’t quite there yet.

  2. I really enjoy your acticles. Straightforward and right to the point. This site is a very good resource for an easy to understand explanation to common problems we face everyday. Thanks!

    • Which ones don’t work? I mentioned specifically that some of these methods don’t work in all versions of IE. Is there one where I didn’t mention it that isn’t working for you?

      If you can offer some specifics I’ll check the methods not working again and amend the post if needed.

  3. I’m trying to make a photo gallery showing thumbnails of an image folder, so there are different image heights. My current solution is a table layout, but it won’t adapt the number of columns to browser width. The line-height method works for the images alone, but the title line below is lost.
    Do I have to invent some javascript that sets the margins? Is it at all possible to call a javascript several hundred times on each image individually?

    • I wouldn’t think Javascript would be necessary here. Did you try any of the other methods. The line-height method isn’t going to work once you have 2 lines of text or in this case a line of text and an image.

      You might want to try 2 containers. Wrap one around the image and the title so you can set the title right below the image and then center their container inside another container. One of the other methods will still be a better option.

  4. Hello mate,

    Nice post. But are you sure that IE6 is gonna take this? I didnt try though. How is this idea? If I take the image source by js, then remove the src and set the image as the background of that div in center center position?

    Thanks

    • It should work except where I mentioned otherwise.

      I’m not sure why you’d need javascript to set a background image. Are you dealing with dynamic images where you won’t know the source in advance?

  5. Thank you Mr. Bradley for your answer. It made me review your methods to try combining the table method with the floating fixed-sized divs that made my gallery of images shown as “slides” automatically adapt the number of columns to the browser width. And it WORKED! Assigning the fixed-sized “slide” divs a “display: table” and adding an extra div to contain both picture and title text with “display: table-cell” and “vertical-align: middle” made the contents centre vertically. Coloring the div borders during testing strangely showed that this extra div doesn’t scale to match the contents but expands to the same size as the table div, but as it doesn’t show it doesn’t matter.

      • In the example both results should have an identical line-height of 38px. However, the lower result defaults to a line-height of 15px because it’s not able to read the single font declaration.

        When I break the single font declaration into font-size, font-weight, font-family; the line-height behaves as it should.

        • Oh I see now and I also have an answer. Where you have the code for .blue-button you’re using the shortcut for font. Even though you aren’t specifically setting a line-height, the shortcut property is setting it for you.

          When you use the font shortcut all the properties you aren’t setting get their default values so the line-height for .blue-button is being set at 1 or 15px even though you didn’t include it.

          Instead of using the shortcut if you write out each property like below you won’t be redefining the properties you aren’t setting.

          .blue-button {
          font-weight:normal;
          font-size: 15px;
          font-family:Georgia, Times, serif;
          }

          I tried and the above works fine.

  6. Hello Steven,

    Here is someone all the way from Bulgaria :). As others shared your article is really great! Good job! Obviously you’ve spent much time to write, test and explain everything in a understandable level.

    Really, I’ve never seen so many helpful ways for vertical centering in one place!

    Best Regards,
    Georgi Yankov

    • Thanks Georgi. I’m glad you liked the post. I can’t take credit for the methods, since none of them are my creation, but I did my best to find as many as I could that would work and put them all in one place.

      • By the way Steve, doesn’t your e-mail notification work as I checked “Notify me of followup comments via e-mail” below, but haven’t received a note about your reply so far.

        It’s just for your feedback. However I did read it as I came back to the post.

        Regards!

        • It should work. As far as I know it does. You’re the first person who’s mentioned it not working. Sorry about that.

          When I get a chance I’ll take a look and see if I can spot why you didn’t get the followup email.

          • Now I received a notification for your comment above…strange…

            For your information the very first time when I wrote my comment and before sending it I was offered to type a number as a check. So I did and everything looked fine since my comment was posted. Then I was on my work computer.

            Afterwords and now I’m writing from my own computer and as I received already a notification it seems fine. Both times I used my email: georgi.s.yankov@abv.com (giving you to check if I have missed to type it correctly) and you can check it.

            However, don’t know exactly what have caused the issue, and apologize for bothering you. Take it just as a feedback which might be in help.

          • That is strange. I wonder why you didn’t get the first one. Let’s see if you get this one. :)

            Maybe it was something in the check or the different computers. The subscribe to comments thing is a popular plugin.

            No need to apologize. I’m glad you’re offering some details to help me look. I’m actually close to putting up a new design for the site. Hopefully the issue will just clear itself up then as I’ll be using some different plugins too.

    • Just wanted to add for anyone reading that apparently the problem Georgi had in commenting was due to the plugin I use to help prevent spam comments.

      I’m not entirely sure why, but the plugin flagged Georgi as a possible spammer (which he clearly isn’t) and so wouldn’t let his comment through. I’m guessing it was originally because of an IP address that had been flagged and then once in the system it’s flagging other things like his email address.

      I’m planning on switching to a different plugin when I redesign the site, but if anyone else has similar issues commenting please let me know. Thanks.

  7. Hi Steven, it’s been a while since I was here. Much thanks for this post, it proved helpful in accomplishing a CSS task that was bugging me.

    Getting ready for the second half of baseball season,
    Rudy

    • Nice to see you again Rudy and glad I could help with the css. I was in New York last week. On Sunday I was at old timer’s day. It was my first game at the new stadium.

      I’m ready for the second half too.

  8. Hi Steven,

    Excellent post. It helped me to fix a vertical centering issue that i was struggling with.. I m gonna bookmark this page as I am sure I will be soon getting back to this. Thanks again for taking the time out to explain things so clearly!

    Best Regards!

  9. Hi Steven, nice post.

    I´d like to ask you about vertical centering a child element with a variable height.
    This is the case, for example, when inside a parent div of fixed size I want to center vertically a child div with a variable number of rows of images, and sometimes there is 1 row, and other times it could be 2 or 3.

    Thanks in advance

    • Thanks Manuel,

      Sorry it’s taken me so long to respond. I’ve been thinking about your question, though I don’t have a good answer for you yet. I’m thinking I’ll look into it more and see if I can put my thoughts together in a post.

      My initial thought is you’re going to need javascript to figure out the height of the child element and then once that’s known it shouldn’t be too hard to center it with one of the methods above.

      I’ll think about it more though, and see if I can come up with something better or at least more specific for you.

    • I just took a look at your Fiddle. It looks like everything is center vertically. Does that mean you got things working?

      Any of the methods here should work for vertical centering, except where I mention they don’t work in IE.

      To center things horizontally you need to specify a width on the element and then set the left and right margins to auto. Some versions of IE also have an issue about quirks mode so you need to use a proper doctype in order for the centering to work.

      Hope that helps.

  10. Your writeups are great, particularly as you summarize *in which scenarios each technique is appropriate *.

    This is so helpful, as when looking for a solution, one often runs into many techniques, and it’s not immediately clear which to use, and hard to keep track of when having many tabs of solutions open.

    keep it up!
    -S

    • Thanks Steven. I appreciate the kind words. I hear you about finding all the different techniques and not knowing which one is best. Sometimes you just have to try them and see which is the right one.

      I tried to offer some thoughts about when each of these works best, though I’m sure there are more pros and cons to each.

  11. Holy wow. Just stumbled on this while searching; your “Absolute Positioning and Negative Margin” is a GODSEND.

    Previously, I had been using tables/table-cells to achieve the same effect, and figured something had to be better…

    So. Thank you. Very, very much.

    • Thanks Aidan. I’m glad the post could help. I wouldn’t say the table and table-cells method is necessarily worse. Just different. I think any of these methods can work well under the right circumstances.

      If you’re interested I wrote a follow-up post looking again at these methods where the content inside is somewhat unknown.

  12. Another best trick that you have left out is this http://css-tricks.com/centering-in-the-unknown/

    i think this beats all the ones here i thought table-cell was most practical here and useful but it has problems: a) child expanding in both directions to parent if parent is block. b)if parent is display:table; then auto margin trick to center parent horizontally doesnt work. So in the end you get to align child vertically but now parent cant be aligned horizontally. This is of course all problem for the div with dynamic dimensions.

    • Are you referring to the ghost element trick? I think all the others mentioned in Chris’ post I covered here. Unless I missed something.

      With the table-cell method you’re right that margin: auto doesn’t work, but couldn’t you just use text-align: center on the parent’s container? Alternatively you can wrap the parent that’s set as a table with a container that exists solely to apply margin: auto.

  13. the “CSS Table Method” doesn’t work and cant work for the simple reason that both the table and the cell will only be as big as their content whereas they would need to be as big as the screen to centre the conent on the screen.

    • And yet it does work. Imagine that. I think you’re expecting the method to do something it’s not intended to do. These methods aren’t specifically to center something on the screen. They’re meant to center an element inside its container.

  14. Or… you could just use a table! (gasp!)
    (I tried several of these and they did weird things, I swear…)

    Test title
    subtitle

    • You could use a table depending on what you’re specifically trying to center, but an html table solution probably doesn’t belong in a post specifically about css solutions.

      Which method gave you a weird result? All of these methods do work.

  15. Note: CSS tables are not the same as html tables.

    Why is this this so difficult for devs to understand?

    Positioning with table properties works well, and has nothing to do with the semantics of markup.

    Thanks for an excellent write-up, Steven, some excellent points.

  16. Best vertical centering article that I have ever read.
    No matter how many times we read, vertical centering will have to be referred over and over again.
    Nice way of explaining things. I’m bookmarking your site :)

    • Thanks Jaz. I’m glad you found the post helpful.

      Once we start using flexbox and css grids and regions and a whole host of css layout stuff that’s on the way, vertical centering will become pretty easy.

  17. The original article was written in ’11; now it’s ’13. Flexbox is still not viable? Sigh.

    When setting an element display:table-cell, is it required that the parent be set as a table?

    I like the table-cell method for its use in responsive designs. Of course, others work as well, but I feel like the table-cell method might have lease amount of markup.

    • Flexbox is close. Hang in there Mary. Of the major browsers it’s only Opera Mini and IE9 and below that don’t have support. There’s a polyfill for IE that worked with the older flexbox syntax, which I think is being updated for the new. I’d say once that polyfill is ready, flexbox is viable.

      I think you do need to set the paren as a table if you want the table-cell to be vertically centered. Not all elements allow vertical-align, but table does. I suppose it could work as long as the parent is something where vertical-align works, though it’s not something I tested.

  18. It’s nice to see all the different methods to align something to the moddle, but how can I align an element of which I do not know the height to the middle?

  19. Until I realised to use the vertical-align on the source rather than the container I could not ever get va to work. Many thanks for the excellent descriptions. Now I have to work on a css substitute for the elegant html tag . :)

  20. I have been using the following solution (with no positioning, no table-cell/table-row and no line height) since over a year, it works with IE 7 and 8 as well.

    .outer {
    font-size: 0;
    width: 400px;
    height: 400px;
    background: orange;
    text-align: center;
    display: inline-block;
    }

    .outer .emptyDiv {
    height: 100%;
    background: orange;
    visibility: collapse;
    }

    .outer .inner {
    padding: 10px;
    background: red;
    font: bold 12px Arial;
    }

    .verticalCenter {
    display: inline-block;
    *display: inline;
    *zoom: 1;
    vertical-align: middle;
    }

    Line 1
    Line 2

  21. Is there is any method for vertical align a container with in the body as example in body of my website i make a container which is center from horizontal but not center from vertical
    is this make sense ???

    • I think I understand what you want. The difficulty is that you don’t know how much height the viewport will have,

      I think a few of the methods above can still work. I’m thinking either CSS tables or the absolute positioning method. You’d want to use relative measurements for everything and you may need to create a container between the body and everything else. Then center the container inside the body.

      Hope that helps.

Leave a Reply

Your email address will not be published.

css.php