If you know the exact width/height of an element, you can center it smack dab in the middle of its parent element easily with this classic trick: top and left set to 50% and negative margins half the width and height of the element. That’s great if you know the width and height of the element you’re trying to center, but what if they are percentages?
You’d think you could just use negative percentage margins. That works for horizontal margins, but margins are based on width (even vertical margins) so it breaks down when you try to use negative top margin to pull things into place.
There is a little trick involving a “ghost” pseudo element and inline-block/vertical-align that is pretty darn clever. But that requires the element you are centering to be inline-block and that’s not a real common scenario. More likely you’re trying to center something like a modal window right in the center. And with small screens / responsive design being big business, it’s highly likely you’ll want your dialog box to be of percentage width (or otherwise unknown like have just a max-width).
There is a way! I saw this trick used by Mary Lou over at Codrops and her article/demo Nifty Modal Window Effects.
Instead of using negative margins, you use negative translate()
transforms.
.center {
position: absolute;
left: 50%;
top: 50%;
/*
Nope =(
margin-left: -25%;
margin-top: -25%;
*/
/*
Yep!
*/
transform: translate(-50%, -50%);
/*
Not even necessary really.
e.g. Height could be left out!
*/
width: 40%;
height: 50%;
}
Use whatever prefixes you need these days.
There we are then:
Check out this Pen!
Nice trick, this will be helpful, I always have “issues” with which approach should I use for vertical centering.
Moore usefull for real vertical align.
Decent support, needs testing when using, but definitely nice!
If you’re wondering – http://caniuse.com/transforms3d
Actually, the support is even better than you think because that’s only a 2D transform.
http://caniuse.com/transforms2d
And here are some polyfills for the other browsers:
https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills#css-effects-modules
This isn’t a 3D transformation.
-> http://caniuse.com/transforms2d
The support for 2D transforms is slightly better.
This is a 2D transform … http://caniuse.com/transforms2d
My mistake, sorry!
Thank you guys! I just quickly googled ‘caniuse transform’ and that popped up. Indeed a much better support than I thought.
This is really awesome! Great solution! Thanks for sharing!
That’s a very nice trick!
Your beard is HOT.
speaking of codrops, that site is cool , lots of nifty UI demo , at some point it just sucks IE still left behind in CSS3
You can also use a combo of right+left or top+bottom to centre an absolute percentage-defined element without the transform:
http://codepen.io/anon/pen/bKuxJ
This is slightly different in the way it’s measured, but it ends up the same as your example would be if border-box were applied.
Yes to this solution. I was going to post this, but I saw someone else beat me to it. For those too lazy to jump to the codepen:
Width and height independent, fully scalable, perfectly centered.
That was is awesome too, probably with a bit higher support. But note that implying right and bottom along with top and left implies a width and height even though you don’t use width and height.
The transform method (despite the example in the article and title of article) works without needing to know the width/height.
Here’s with totally expandable both width and height: http://codepen.io/chriscoyier/pen/Lgaij (try clicking in an editing the text).
Did someone tryied to open this on iPad?? Something weird happens and the container fall down the screen!
It would be nice if we could find a similar approach for non fixed width/height elements.
Try it… this solution works perfectly for that issue!
http://cdpn.io/cmFaj
That’s new to me!
You can apply that to not only percentage-sized elements, but to elements with automatic width and height! That’s really good!
To bad you have to drop IE8 support…
Terrible support for IE. What a shocker… :)
VERY sweet. This also works for auto height and width.
Not bad, not bad.
I prefer the “TRBL” method:
I use it all the time and works down to IE8.
That’s also quite nice, didn‘t know about this one.
(But I suppose it only works if width and height are explicitly given, and not for auto?)
@ChrisB
This method does not need an explicit width and height set at all. You can do
And it will work just fine. See this pen that Ben posted a few comments up.
I think the big difference between the 2 solutions here lies in the layout of the content box. Check the background color of the box with the transform 2D approach and no width/height. It is not painted as big as with the TRBL technique (which, btw, should work in IE7 too).
It is also possible to vertically center an element even without knowing its dimensions with a combination of line-height, display inline-block and the new vh css unit: http://codepen.io/anon/full/mkFDK
(won’t work in IE, unfortunately)
omg this is rad… it even seems to work with height:auto
Hey Cris –
Your last post [Centering Percentage Width/Height Elements] was freaking awesome. I have gone ahead and added your stuff to my Feedly account. Please keep me updated if you post anywhere else.
Keep rocking –
Jon
Agreed, thats very cool
Very Nice. Why it does not work in jsfiddle
http://jsfiddle.net/fizerkhan/BFqA2/
You’ll need to prefix the transform. I have -prefix-free turned on in CodePen.
Nice trick ; however, I encountered some problems while testing it. Indeed, it seems that there’s a problem on Chrome with transforms and borders. Depending on the parity of the width/height.
If one of the dimensions is odd, then its 50% value is not an integer and the border is blurred in some cases, or have an offset in others.
Here’s a fork of your pen that illustrates the problem. Try playing with the size of the window to see the offset appear in Chrome.
Matt, while that is an odd problem, you can fix it by adding background-clip: padding-box. Here’s my fork of yours.
Nice tip, very useful.
Thank you! Thank you! Thank you! This is exactly what I have been trying to achieve for the last week with not one, but two projects. As noted above, it even works with height:auto, so I no longer have to distort the image.
Great solution, thanks! :)
Pushing Ben’s technique above to include overflowing content:
http://codepen.io/jacmaes/full/EFLjG
Thank you Chirs, for telling me another CSS trick, previously I was using relative postion to center my absolute div
Please suggest which one is more better
http://codepen.io/Shaz3e/pen/zaFbx
Awesome…Thanks for sharing this handy tip…
That`s why I love to read this blog!! Great CSS-Trick
We can use this for vertical center and horizontal center.
.center{
width:500px;
height:500px;
display:table-cell;
vertical-align:middle;
text-align:center;
}
Actually, if you do have width and height of the element, the easiest way is to use negative margins, like this:<br/>
.center {<br/>
width: 300px;<br/>
height: 300px;<br/>
top: 50%;<br/>
left: 50%;
margin-left: -150px;<br/>
margin-top: -150px;<br/>
}
I FOUND this article very nice
If you positively must at all costs support legacy browsers, shall we not forget the Javascript solution (using jQuery):
Demo
Using jQuery for such things is just a huge overkill… :(
For this to work, I needed to add + ‘px’ to both of the margins.
@LorDex Since I am using jQuery all over my project, I don’t think it is overkill at all.
helpful in responsive websites.
I totally ran into this last week with the Nifty Modals (http://tympanus.net/Development/ModalWindowEffects/)! I thought it was really cool, but a negative side effect is that we noted in some browsers (Firefox did this the most), it uses some smoothing to do this transform, and if you have something complex in the modal (in our case, an ExtJS grid and some other components) it causes all kinds of weird issues with the scrollbar and causes a strange anti-aliased look on everything. I ended up having to use the negative margin trick instead to make it work.
Cool. This also helped me center a width: auto element between a fixed width and another with: auto element.
Using display: block and margin: 0 auto often works nicely too.
Yeah, but that doesn’t center vertically.
I have been looking for the vertical align for responsive Div or Images for few days now, that would aslo work in IE browsers. Finally, I just experimented on my own and came up with this, that seems to work the best so far, with no additional hacks using CSS3 :after or translate() properties… Let me know if it works for you, too, pretty straight forward:
The margin of the div becomes it’s vertical centering agent, so to speak.
I’ve bin waiting for that one for a long time…
Can’t wait to try it!
Tx.
Nice Trick, it’s help full for me.
What about using flexbox?
(This assuming the item being centered is the only thing in the document, else html could be .container or whatnot.)
Obviously, with prefixes like -webkit-box, etc…
Great trick – having issues on Safari however. Will try some of the fixes listed in the comments. Thanks for sharing!
This is probably the best CSS only method for centering an element of unknown height vertically. Nice trick. In Chrome I’m seeing some font rendering issues. Maybe what @Nathan St. Pierre was talking about. Apparently Chrome’s making the text content of the element with transform: translate(-50%,-50%). I looked at it on an iPhone 5 and the text is sharp.
The remaining issue I have is when the element being centered vertically with this method is taller than the window, like when viewed in landscape orientation on a phone, the top of the element is off screen. So I’m still using a method like @Yotam mentioned to center vertically only if the window height is greater than the element height.
I meant to say Chrome’s making the text content of the element with
transform: translate(-50%,-50%)
blurry. Seems like a weird bug. Haven’t seen this before.This drives me nuts:
This is codepen from this article with reduced styling: Screenshot 1.
And this is the same code brought to my codepen, saved (using firefox), and then opened in chrome: Screenshot 2.
The same exact thing happens to my modal on my site…
As you can see, the code is the same in both examples. Why????!!!
Resolved:
add webkit line:
-webkit-transform: translate(-50%, -50%);
It’s likely that the -prefix-free option is checked in the CSS options in the first example.
With this solution, the centered div looks very blurry in Google Chrome 31.
Some mobile browsers (Android 2.x) are not able to use translate() with values in percent.
So this works great except in the scenario where you have an image, set it to 100% height (which causes the width to be wider than 100% of the container). Any ideas on how to center an img that ends up being > 100%?
CSS:
Here’s a code pen: http://codepen.io/napawapa/pen/soeGz with my example with image in place.
oh my god you are a BIG hero for me ! this is SO CLEVER!
Great fix, thank you!
I couldn’t get some text to center on top of an image while using skelton.css. The responsive design meant you had to have all the boxes be the same size or individually fix to center based on the column amount. This was much easier, would recommend for responsive sites.
Great post !
Some reminder for those stuck as I was 10mn ago:
Use position:fixed instead of position:absolute if you have a scroll on your page.
Thank you! I was trying to figure out a solution for this for such a long time. You rock.
Oh thank god, finally somebody had an idea other than “tables” or “ghost element”. Those don’t work with the constraints I have to handle for my project! — /This/ approach works perfectly, thanks a million!
Thanks, neat trick.
I don’t see how this is centered… not working any more it seems.
Using Firefox 29 and Chrome 34
It works fine in both of those browsers fine (the demo in this very blog post). Make a Pen with your “not working” situation and post that if you’re having trouble.
Burying for now. Will unbury if we discover a true problem.
.center{
position: absolute;
height: 50px;
width: 50px;
background:red;
top:calc(50% – 50px/2); /* 50% – height/2 /
left:calc(50% – 50px/2); / 50% – width/2 */
}
Keep in mind calc() is not supported in IE8
FINALLY!! You freakin GENIUS did it!
thank you!!