Centering in the Unknown
Published by Chris Coyier
When it comes to centering things in web design, the more information you have about the element being centered and its parent element, the easier it is. So what if you don't know anything? It's still kinda doable.
Not too hard: Known Child
If you know the height and width of both the element to be centered and its parent element (and those measurements won't change, i.e. not fluid width environment) one foolproof way to center the element is just to absolute position it with pixel values so it looks perfectly centered.
Let's say you know the exact width and height of the element you are centering, but the parent element can change in height and width.

You absolutely position the element to be centered and set the top and left values to 50% and the margin top and left values to negative half of the elements height and width. That was a tounge twister, so check this out.
Harder: Unknown Child
The hard comes in when you don't know the dimensions of the element to be centered.
The grossest way to handle it is literally tables:
<table style="width: 100%;">
<tr>
<td style="text-align: center; vertical-align: middle;">
Unknown stuff to be centered.
</td>
</tr>
</table>
If you are worried about the semantics of that, you could attempt to match it to your content.
<div class="something-semantic">
<div class="something-else-semantic">
Unknown stuff to be centered.
</div>
</div>
And get the same result as the tables like:
.something-semantic {
display: table;
width: 100%;
}
.something-else-semantic {
display: table-cell;
text-align: center;
vertical-align: middle;
}
CSS tables might be fine for you. Or it might not. Tables do render a bit differently than just a regular block-level div does. For instance the 100% width thing. A table will only stretch to be as wide as it needs to for the content inside it whereas by default a block level element will expand to the width of its parent automatically. Also, god help you if you need other content inside that div that you want to position or otherwise not act as a table-cell.
Michał Czernow wrote in to me with an alternate technique that is extremely clever and accomplishes the same thing. If we set up a "ghost" element inside the parent that is 100% height, then we vertical-align: middle both that and the element to be centered, we get the same effect.
So does that ghost element need to be an un-semantic element? Nope, it can be a pseudo element.
/* This parent can be any width and height */
.block {
text-align: center;
}
/* The ghost, nudged to maintain perfect centering */
.block:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.25em; /* Adjusts for spacing */
}
/* The element to be centered, can
also be of any width and height */
.centered {
display: inline-block;
vertical-align: middle;
width: 300px;
}
View Demo
I'd like to tell you the ghost element technique is way better and should be the go-to centering technique for the ages. But in reality, it's just about the same as the table trick. The browser support for this is essentially everything and IE 8+. IE 7 doesn't support pseudo elements. But it doesn't support CSS tables either, so it's a horse apiece. If IE <= 7 support is needed, it's <table> time (or use an equally un-semantic <span> or something for the ghost element).
This stuff isn't brand new territory. Gary Turner wrote about it like 5 years ago. But I credit Michał for doing it with a pseudo element and making it the most semantic approach yet.
Note: The 0.25em nudge-back is a little janky. To do it perfectly, you could set font-size: 0; on the parent and then notch the font size back up inside the content container.
The example link is broken. Nice technique! Thanks! =)
Looks like JSfiddle is down. Hopefully it will be back up soon.
I have been looking for something like this. Can’t wait to see the demo :)
I think it is a real good example! I am also waiting for the demo…
Very cool, I’m going to start using this! What’s really funny is that I miss using the old <center> tag because it would automatically horizontally center everything for you. Oh well :P
Why would you want to add superfluous markup for something that can be done with a simple text-align:center in the style sheet?
I don’t see the advantage to adding the “ghost element.” Can you elaborate?
CM
The ghost element is 100% height of the parent, so anything vertically-aligned with it will be centered with it. It’s what makes the whole thing work.
I tried in your demo add a span within an html conditional comment for ie7-, defining the same properties (except by content), but that doesn’t work. So I changed the div’s by other span’s (due to the ie7- bug for assign inline-block to an natural block element), and worked!
That’s a shame for semantic and code validation, but is better than use tables, is not it?
The example: <a href=”http://jsfiddle.net/vTQBs/”>http://jsfiddle.net/vTQBs/</a>
Sorry, the updated test: http://jsfiddle.net/wFPhW/
This generates so much code in CSS to avoid a simple 4 lines.
Please tell me how a <table> is not semantic enough for this application ?
A table is an element to represent data, any other usage of it will not be semantic.
Also you can make this CSS code reusable and then you can use it everywhere in your site like the “clean clearfix”. You gain in semantic and mantainability.
I think is a great snippet.
Thank you Chris
Seriously, are we still having this discussion? It’s 2011.
In all seriousness, having a .centered class isn’t semantic either. It introduces design specifications into your html.
Should the declaration
vertical-align: middleis placed on the selectors that containdisplay: table-cell? One day I ever sawvertical-align: middleis placed on the selectors that contain the declaration ofdisplay: table(the parent element)Then there’s (hopefully) the flexbox:
box-orient: vertical;
box-pack | box-align: center;
And no word on how centering vertically is a progressive enhancement with jQuery being the master manipulator ? ;)
Bravo! I was actually going to have a sit down and see if I could come up with something like this but this is way cleaner.
Wouldn’t
<div class="wrapper"><div class="inner">content</div></div>
with
.wrapper { float: left; position: relative; left: 50%; }
.inner { float: left; position: relative; left: -50%; }
work in this situation and be more elegant?
of course – doesn’t vertically centre. apologies…
Awesome little technique! It makes me wonder how much untapped potential the :before and :after pseudo-elements still have.
The more people realise how useful they are, the cleaner, I believe, everyone’s code can become.
Not crossbrowser of course, but anyway.
Did you mean transform? And it’s cross-browser solution for the latest final versions of all major browsers (except IE10)
It’s a very clever way to do that I didn’t know. Thanks !
But that’s a shame there is no straight way to do something THAT SIMPLE. I really think css should be rethink from the start.
Chris, when you don’t know the size of parent, but the size of the child is known, then there is another method of centering via pure CSS:
Stu Nicholls did a similar demo back in 2006 which might prove useful. He wrote about his solution:
Here’s the link to his demo:
Centering an image of unknown size in an outer container of known size
Does inline-block’s gap always has 0.25 em?
http://www.lifeathighroad.com/web-development/css-web-development/inline-block-whitespace-workaround/
What I haven’t been able to figure out yet is if I have an anchor wrapping around a div, let’s say 200px x 200px.
I want the entire div to be one big link, not just the text inside. Sometimes the text will wrap to two or more lines. I want the text centered vertically inside the entire block level anchor.
Not worried about ie6 support but if anyone can do this and show an example I will send you $10! :)
Might help with a little illustration if I’m not clear:
———————————————
|
| This text and entire
| surrounding should
| be centered and clickable
|
|
———————————————
To make an entire div a link, you can use “onclick” like this:
onclick="location.href='http://css-tricks.com'"To make it appear as a link, you’ll also need to change the cursor in the css.
cursor:pointer;Made an example for you:
http://jsfiddle.net/R2eDQ/
Hope I could help!
Great trick, but the title ought to be “Centering -OF- the Unknown” :)
The solution solves the problem of vertical centering when the height of the centered block (as opposed to its container) is unknown.
It requires that the container have a known and fixed height.
No it doesn’t?
I miss the deeper explanation of the solution.
- What is happening exactly
- Why do you need them both “middle-d”?
Hey Chris,
for me it’s the same as for Mark. When I set
because I don’t know the height of the browser window, all stuff inside went to the top. :( Did I miss something?
Greetings from Berlin.
Yes, I miss!
All objects before have to be at height: 100% too.
Ferge,
You’re right, vertical centering didn’t work for me either until I set html/body height to 100%.
Chris,
A curious thing happens when I minimize browser window to less than the specified content width — I get a vertical scroll bar, and content drops below the viewport. I fixed it by setting min-width of the body to match content width. Resulting CSS:
html, body { height: 100%; margin: 0; }
.wrap { width: 100%; height: 100%; text-align: center; }
.wrap:before { content: “”; display: inline-block; height: 100%; vertical-align: middle; margin-right: -0.25em; }
.centered { display: inline-block; vertical-align: middle; width: 960px; }
body { min-width: 960px; }
I’ve been needing to do exactly this; a centered, variable-height image within a known parent, with a caption aligned underneath the image. I simply don’t think this is possible without JS :(
Every period has its own techniques. Several years ago, we did know about the limitations of the browsers, so pseudo-elements were not an option. Bruno Fassino tested the combination of display: table-cell for “modern” browsers, combined with display: inline-block hacks for IE. http://www.brunildo.org/test/vertmiddle.html and http://www.brunildo.org/test/img_center.html
Gary Turner’s article describes the technique very well. And Chris Hester already noted that Stu had similar tests and solutions.
Seen from today, it is short-sighted to point out these solutions as “un-semantic”. It was the best you could get at that time — you are standing on the shoulders of giants.
Hey Chris, here centering a div on a page made easy :) working in any possible browser, or at least in all I tested.
The whole article here: http://www.kensfi.com/how-to-align-center-a-div-with-no-width-declared/
btw 2 lines of CSS and valid markup :)
here again, sorry… just tired after the day.
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title>Untitled Document</title>
<style type=”text/css”>
ul { text-align: center; }
li { display:inline; padding:0 10px 0 0 }
</style>
</head>
<body>
<div>
<center>
<ul>
<li><img src=”http://www.kensfi.com/images/pict.jpg” width=”200″ height=”166″ /> </li>
</ul>
</center>
</div>
</body>
</html>
Finally! I’ve tried so many techniques to center elements inside a wrapper and this is far best I’ve seen
Congrats and thanks for sharing!
Funnily enough I had this exact same problem yesterday and resorted to using a nasty old table. I do need support for IE7 so I guess will leave it as-is for now.
Thanks for sharing :)
Very useful!
the real question is: why didnt w3c try to figure this one out since ages? may be becuase centering vertically is not a style related issue, or thats how w3c see it! to me, centering vertically to an unknown parent is very much a dynamic-visual effect, thus belongs to behavioral layer… javascript that is. e.g. lightboxes, u already need js to pop open the box, u might as well let js position it.
visual effects proly assume knowledge of parent width.
Damn, CSS is ugly. Take a look at AXR Project (http://axr.vg). This thing will take you 3 lines of code.
So why are you at CSS-Tricks…?
So why are you at CSS-Tricks…?
Just to be clear, using unsemantic code purely for layout purposes is correct.
We use divs to wrap our content because they have NO semantic meaning, not because they have the right semantic meaning. The same goes for spans.
Using a table, in this case, is incorrect because tables have an inherent semantic meaning.
By using spans and divs, we are not getting the semantics wrong; we’re just not being semantic at all. In this case, it is a good thing.
Am I right, Chris?
The solution I use is the same as Chris’s original solution but extended to be browser & version compatible…so, Chrome, Firefox, Opera & IE (6 through 10).
You don’t need to know any height or width and works in every major browser + versions for the last 10 years.
No JS, just CSS hacks…
Demo:
http://www.mattpass.com/lab/hCenterVCenter
The CSS…
.mainContainer { position: absolute; display: table; width: 100%; height: 100%; top: 0px; left: 0px; text-align: center; } .mainContainer .vCenter { #position: absolute; display: table-cell; #top: 50%; vertical-align: middle; text-align: center; } .vCenter .heyImCentered { #position: relative; #top: -50%; text-align: center; display: inline; background-color: red; color: white; }Can’t claim I created this solution, but thought I’d share it with people! :)
Cool
this will come in handy! but how does inline-block behave? I’ve used inline-table and inline before.
When centering the “table-cell” element, don’t forget to remove the float:right | left.
Otherwise the vertical alignment does not work.
Heya, Thanks for sharing this!
I wonder what would be that case when I need to vertically center something and the text must be aligned to the left side?
I have a site with collected poems and I just can’t figure out a bullet-proof solution, because every poem has differing line widths.
Plus it’s a typographic expectation that the title of each poem should be in the center of the avarage line width.
Would be so happy if you could think about this for me.
Cheers,
Greg