Vertical align anything with just 3 lines of CSS

Published January 13, 2014

With just 3 lines of CSS (excluding vendor prefixes) we can with the help of transform: translateY vertically center whatever we want, even if we don’t know its height.

The CSS property transform is usally used for rotating and scaling elements, but with its translateY function we can now vertically align elements. Usually this must be done with absolute positioning or setting line-heights, but these require you to either know the height of the element or only works on single-line text etc.

That’s all you need. It is a similar technique to the absolute-position method, but with the upside that we don’t have to set any height on the element or position-property on the parent. It works straight out of the box, even in Internet Explorer 9. To ensure browser compability, remember to add the proper vendor prefixes. At the time of writing, you need -ms-transform and -webkit-transform to make sure it works everywhere.

Update (April 25th, 2014)

As a few people have pointed out, this method can cause elements to be blurry due to the element being placed on a “half pixel”. A solution for this is to either set its parent element to preserve-3d. Like following:

Comments ( 391 )

Great technique! And features like Flex Box and Grid Layout will make this kind of thing even easier.

One thing I would point out: Some of your vendor prefixes are redundant. Opera never shipped an -o- prefixed version of transforms and, now they have switched to use Blink instead of Presto, they never will, so you can safely remove that one.

Mozilla did ship Firefox with a -moz- prefixed version of transforms, but it has supported the unprefixed version since Firefox 16. The number of people still using versions of Firefox older than 16 is tiny, far less than those who are using IE8 and below, for example, so it’s probably safe to forgo the -moz- prefixed property as well.

If it’s an unnecessary prefix, stopping bloat is a very sensible reason to remove it. If you’re using a task-runner based workflow and you do want to retain it, you could always use a tool like Autoprefixer and set the necessary level of fallback.

I am so tired of “we can pretend Opera doesn’t exist because it uses Blink”. Just because Opera has switched from Presto to Blink doesn’t mean Opera users have. The majority of Opera users are not upgrading beyond version 12 (the last version that uses Presto). Reasons range from the browser not auto updating to Opera gutting half of the features it used to have.

opera (presto) supports quite a lot of standards and most of them in an unprefixed and same-as-the-spec fashion (unlikely to many implementations in webkit). many newer features actually need a decent fallback anyway, as the new ie6 aka old webkit implementations are the major problems (i’m looking at you, smartphones).

so just code for new browsers and if its looking ok in opera everything is fine, thats how i am doing it. but i’m also avoiding nearly all prefixes. (i use the unprefixed versions of everything and don’t bother the clutter)

Its nice idea to avoid all prefixes, but latest version of Chrome (which is most popular browser today) doesn’t support many new features such as @keyframes. I wish Chrome was powerful and updated as Mozilla Firefox.

Yes, but read the full context: “Opera never shipped an -o- prefixed version of transforms and, now they have switched to use Blink instead of Presto, they never will.” In other words, pre-Blink Opera didn’t use a prefix, and now that it’s using Blink, Opera never _will_ use an -o- prefix.

For those that think display:table is better. I think it has drawbacks. For example, word-wrap:break-word; is a bitch to implement. Personally, I think this technique is much cleaner and better than the display:table one.

Nope. If your only aim is to vertically center the content of an element, you don’t need display: table parent.
Table cell-like elements also works like division elements that automatically shrink to the content width, and don’t take up the whole horizontal space.
The problem with table-cells is that they behave like… table cells, with everything that comes from actual tables. So no matter how you size it, it will always expand to fix its content. And in Firefox you can’t absolutely position elements inside it, because of a 14 years old bug…

Hmm, that did not work for me. I tried to add an image to a div and set the image style to “display:table-cell; vertical-align:middle”, which did not work.
Then I added another container div with that style and placed the image inside it… that came out broken in a different way.

Fun story, it can completely crash Safari. We couldn’t figure out why our app was completely crashing when logging in. After a while bisecting we found a big CSS commit. 1 by 1 we went through the CSS properties removing each one. It was calc. Mobile and desktop Safari both!

Along with it, lenders based in the ways previous generations did. Do you want to regret your choice after youve signed the application. Learn how to effectively and economically tap their commercial pre;#rty&o8217ps equity.

It took me a little while to figure out exactly how it worked to center something inside the whole viewport (i.e. a modal window). In case it helps anyone, here is a pen I created: http://codepen.io/webinsation/pen/GCuhm

It will work in Internet Explorer 9 and up. As well as earlier versions Opera, Chrome, Safari and Firefox from way back. So for IE8 and below I would suggest a Modernizr with Javascript fallback, where you simply calculate the height of the element and then vertically align it with JS and position absolute.

I think this post is appealing to the folks that have tried the display:table technique and found that it was lacking for one reason or another. This is a great alternative and both techniques should be tucked away in the developer’s tool belt.

I find that this breaks down when the element’s height is larger than the container. Which could be an issue in responsive designs where the height often grows as the viewport narrows or in templates where you don’t necessarily know if the element’s height is going to be more or less than the container.

I’ve tried setting min-height on the container rather than height, but it appears that position: relative; top: 50%; then just gets ignored, so the element sits at the top.

I was hoping to use this for those designs where you have different full screen “sections”, each of which is at least as high as the screen (probably with a cover image background) and then the content inside that is vertically centered. It should still work if the content (and therefore the section) becomes higher than the screen. The content should just push the section to be bigger.

The min-height-on-parent-problem is due to a bug in Webkit: https://bugs.webkit.org/show_bug.cgi?id=26559. If you try viewing an example with min-height and the translationY() vertical align method in Opera, you’ll see that it works.

Pretty cool… It kinda seems like it _shouldn’t_ work, even though it does. Shouldn’t top:50% and translateY:-50% cancel each other out? Would be great to see a brief explanation on why it actually works.

Thknsa!!! This rings so true. I love to cook and have been cooking completly clean even my treats are clean, but i have this little problem of tasting food as i am cooking or tasting that first pancake then i have my regular serving. Thanks for a little kick in the butt u are the best!!

Just noticed an issue with using translate on a fixed positioned element in Chrome (32) and Mac OS (10.9):

When a fixed position element is translated this way, it leaves trails across the element. Hard to pinpoint how and why it happened, or when it would happen, but changing fixed to absolute solved the problem.

(Also seemed to have some strange side effects to the font-smoothing on PC chrome, not sure why)

Trying to get this to work on a group of social media icons in the right header area of clemsonumc.org. Currently have to use a top margin of 40px to center the icons vertically, but this leaves a gap between the link text and icons when the site is viewed on mobile or smaller resolutions.

This CSS seems to be the exact solution we’re looking for but I can’t seem to get it to work. Any thoughts? Thanks!

Elm – The weirdest thing just happened. I was on PM, and the dueling system glitched, and I got a Ravenclaw challenge aimed at you. I saw that your current point total was listed as 3920. Then I looked you up on PM and saw again that your points total was listed as 3920. So I came over here to see if you had any news about your points. Are you dueling again, or has PM just resatinted about half the points they deducted?

If I need old IE compatibility I use inline-block and vertical-align.
It’s not as short as the transform method and it requires to add an empty element but it works in every browser that supports inline-block and the sibling “+” selector.

Wow, everyone has an opinion, firstly thanks for putting up your ideas. I like to use wrappers and then position. Can use clear:both to reset and place new div. My reason, pixel perfect placement. As someone doing double major in IT and Comp Sci, using tables is frowned upon and seen as old way. The real issue is browsers not being truly web savvy. The web should be able to reproduce desired layout no matter what the user-agent. This is a flaw with the browser designers, why? Maybe they think they are clever, I don’t know. There in theory should not be any need for m. web pages for example. CSS does not affect html validation. Good luck with your web design. I find experimentation and multiple browser testing works but time consuming. In the end anything older than 5 years is not worth considering. That is my humble opinion. I have settled on chrome, IE10, firefox, and safari.

Hello, this is great technique, and I am using it in combination as:
@mixin abs-aligned {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%,-50%);
-moz-transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
}
But, for some reason this creates blurry effect in IE11, which I can not resolve with any of css applied to parent element.
Any idea?
Thanx!

It seems the height of the wrapping element needs to be set explicitly for this to work? Say, I have a logo of unknown height (plus some padding) floating left, followed by a menu of known height (presumably less than logo), floating right, both directly inside a wrapper. Top 50% doesn’t apply a value. Height of logo may change on window resize (tied to width), so I’m currently stuck using jQuery.

This technique doesn’t work out of the box for me at all. On Mac and PC the only way I could get this to work as expected is to make that transfrom: translateY a positive percentage in addition to the top also being a positive percentage.

Is there more information on the how/why this works? Why does it only work with both percentages being positive for me?

This works, and thank you for sharing! But it only works for elements like maybe some other ones…
However, try to enclose all those sections in and try to align this div using translate technique. It will not work. For example:

Vertical center with only 3 lines of code

I’m vertically aligned! Hi ho Silver, away!

I’m vertically aligned again! Hi ho Silver, away!

The goal is to vertically center enclosing div. The container div always goes on top of the page, not at the center of it. So… it is not working for this particular case.

“…we don’t have to set any height on the element or position-property on the parent.” is a little deceptive. You have to set an absolute height on the parent element. (Remove it from your example to see what I mean.) Otherwise, a fantastic tool. Thanks for posting!

I came across a problem. When the browser view height is little the content of the centered element might get cut. Here is an example(try and remove most of the text. It will be fine then.): http://jsfiddle.net/tfvqb8jL/

I ran this in a fiddle and it looks like it places the top of the child div at the center of the parent div. I was expecting it to place the center of the child div in the center of the parent div. Am I missing something?

I was using table-cell to vertically align a Flash animation, but in IE11 the Flash player wouldn’t play. Investigating, I discovered* IE11 won’t play Flash sometimes (anytime?) unless the page is set to comptability mode. So I switched to compatibility mode and the Flash plays, but is aligned at the top of the page, not in the center. So I found and applied this solution. Now, in compatibility mode, the Flash plays, and the animation aligns… at the BOTTOM of the page. If I turn off compatibility mode, the Flash animation is centered vertically, but will not play. So I’m back where I started. Ain’t IE great?
* http://www.thewindowsclub.com/flash-not-working-in-internet-explorer

For the guys commenting, that it doesn’t work, just make sure the container has a fixed height. Since my content changes height because of responsiveness I just added some JS to change the container height on resize. And it gets the tallest element and uses that height.

This straight up doesn’t work. I have two divs, one nested in the other. Applying this to the containing div does nothing. Adding height 100% to the containing div and then trying to apply this to the nested div, doesn’t work. The divs remain stuck to the top of the page.

This is a great trick. I had previously been using the similar trick with absolute positioning, but this is less code (since you don’t have to mess with the parent element), still allows me to use text-align for horizontal alignment, and I don’t have to deal with any of the other downsides to removing the element from the normal flow of the document that comes with absolute positioning. Thanks so much!

also to align it in center and middle you could use
.element{
top:50%;
left:50%;
position:relative;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50% -50%);
}

This is the perfect website for everyone who wants to find out about this
topic.You realize a whole lot its almost hard to argue with you (not that I actually
would want to…HaHa). You definitely put a brand new spin on a subject that’s been written about for many years.
Wonderful stuff, just great!

My partner and I stumbled over here by a different web
page and thought I may as well check things out. I like what Isee
so now i’m following you. Look forward to looking over
your web page repeatedly.

Fantastic goods from you, man. I have take note your stuff previous to and
you are just too magnificent. I actually like what you have acquired
right here, certainly like what you’re stating
and the best way by which you are saying it. You are making it entertaining and yoou still take care of to stay it sensible.

I can not wait to read much more from you.
That is actually a wonderful website.

I was under the impression that this should be used with position: absolute, and indeed it did not work for me until I changed the positioning to that. I’m not sure why and I’m a little too busy to delve deeper into it, but you should check that out Thanks a lot!

Austin- I’m having this same problem in IE only (so far versions 9 and 11). I haven’t found what is causing the issue yet. This method does work perfectly in all other browsers I’ve tested- Chrome, Firefox, Safari, Opera and SeaMonkey. I’ve also used it successfully for our mobile site. Not sure what the current IE issue is, though- but it’s not like IE hasn’t always been the bane of our existence.

Thank you so much! I’ve been beating my head against a wall trying to adjust the vertical alignment of text on top of a background image, and the text could not be placed as an absolute element, due to the responsive nature of the layout I’m transitioning our primary site onto! I was so excited to see the initial load screen was correct and it displayed correctly as I resized my browser. When I uploaded it to the test area, it worked great on my phone and tablet!

In my eagerness to post, I forgot to mention WHAT it was that I did…the very first portion of your article, the CSS line addition. In my case, I used these three lines to vertically and responsively align my text to the top of a background image:

I’ve been a Tilwmrboeves fan since the beginning. Sometimes it’s been hard, but I’m really starting to get excited about the team again. Thank you Kevin Love. Thank you Mr. Kahn and Coach Rambis. Thank you Michael Beasley. You are going to love Minneapolis and Minnesota.

useful thanks. but note, this only works if your content has less height than the container, otherwise the content will flow above and below the container. Try adding 3 paragraphs of text instead of one, or removing the section height: 150px

Hi Dan, I just read your solution, I wasn’t aware of flex, now I’m digging more about it. Amazing!
I still have an issue : I generate a masonry page full of image items with centered text on images. In some items, text is aligned left. I don’t understand why.

The article is a little misleading in it’s simplicity. There is a missing condition, and that is the `.element` needs to be a block element, which is revealed here:
stackoverflow.com/questions/30587090/when-to-use-position-absolute-vs-position-relative-when-vertically-aligning-with

that’s great! thank you.
before i used on parent display:table-cell;
and on child vertical-align:center, but this way dosen’t work if parent element comes with width:100%; But your code helped me to solwe this.

For the longest time I would use a combo of display:table and display:table-cell to achieve vertical alignment. It’s a bullet proof solution, except you need to create an extra child element, or even both the parent & child, just to make it work.

This solution does not work 100% of the time, but not having an extra element makes it a winner.

Hmm it looks like your blog ate my first comment (it was super long) so I guess I’ll just sum it up what I wrote and say, I’m thoroughly enjoying your blog. I as well am an aspiring blog blogger but I’m still new to evrigtheny. Do you have any tips and hints for beginner blog writers? I’d definitely appreciate it.

Your code works wonderfully if I’m trying to center an element directly to it’s parent, but is there a way to vertical align the element to it’s great-great-grand parent?

I’m not a great CSS coder…just some noob trying to learn!

I’ve read up about child selectors, but in my case the TOP: and TRANSFORM: are referencing to a direct parent which happens to be a “tight” container, and I realized I have to get the TOP: and TRANSFORM: to reference against a great-great-grand parent element.

I want to thank the author of this article, by adding the preserve 3d codes to my css body tag, solved an annoying problem I was having with text blurring only inside a table on a page refresh. Couldn’t find any mention of this type of problem elsewhere so glad to run across this easy cure.

I am using transform: translateY in the website above on the News heading (Distinguished Alumni,…) hover overs.
My question is how do I bottom align the hover over heading text when there is more than one line?
I want the headings to bottom align so they are same distance away from their description.
Thanks.

The problem is, the container must have a fixed height (thus not fluid/responsive in height)… and using ‘max-height’ doesn’t work: strangely, even if DevTools shows that the container has the intended height (the one set with max-height), the image won’t align to it.

It makes no difference if the container has ‘max-height’ or not applied to it, and the image actually gets positioned way above where it should, leaving a blank space below. That is apparently because ‘top: 50%’ does not affect the if the container has no height set in CSS.

So I think I’m better off using the image as background along with ‘background-size: cover’.

Question, though. I’m using this fix on an logo inside a header. When I go from a narrow browser window and resize it to a large browser window, the logo appears cut off, all the way at the top of the browser window — not vertically centered inside the div. If I refresh the page, the logo reappears in it’s vertically centered position.

Thanks for this. I must’ve come here weekly for the past few months. So often that I actually do feel bad when I’m in another tab and the title tag changes to “I miss you.” I’m like, “It’s OK, I’m right here.”

The only problem I see to this solution is if the div that is centered vertically changes it’s height. What happens is the div recenters vertically, I recently had a case where this wasn’t the desired behaviour. Unfortunately for my case I have to do this:
.center-vertically {
position: relative;
top: 50%;
margin-top: -(half-the-divs-height);

it should be noted you may also need to add transform-style: preserve-3d; to elements inside the div being centered. If you have a div being centered and inside it has some text and a button with a 1px border, it may end up putting that button on a half pixel cause an issue where FF wont show the top or bottom border.

Here is a problem… The centered element’s container must have a fixed height, the main reason for using a technique like this is because the container elements has a variable height. So it’s useless. SORRY.

I noticed one slight problem with this on Safari 5.1 on OSX or Windows (but who uses that right!)

if you have a div with padding-top set on a :before pseudo element to keep an aspect ratio, then an absolute wrapper inside that with 100% height, and then try use translateY(-50%) etc on a relatively positioned content div inside that… safari does not work out the height correctly. padding-top seems to be affected by the height of the browser.

Yes I do the same thing – and for me it’s not just osx in a windows vm but on one of my real test macs also running safari. Seems to have no side effects with position attribute being changed like that, so I do suggest this as an improvement.

But this is just not what has it on top, it’s the fact that it
is just a great price with fantastic features and a wonderful
life of the battery that tests show too last nearly ten hours.

Different companies produce the technology products and supply the technology service and support
along with their product. Once the application continues to
be opened, a wizard can provide the instructions
concerning how to use it.