Vertical Centering With CSS

There are a few different ways to vertically centre objects with CSS, but it can be difficult to choose the right one. I’ll show you all the best ways I’ve seen and also how to create a nice little centered website.

Vertical centering with CSS isn’t an easy thing to do. There are many different ways that may not work in some browsers. Let’s review 5 different ways to vertically centering objects, as well as the pros and cons of each method. (You can see my test page briefly explaining all of them.)

Method 1

This method sets some <div>s to display like a table, so we can use the table’s vertical-align property (which works very differently for other elements).

<div id="wrapper">
	<div id="cell">
		<div class="content">
			Content goes here
		</div>
	</div>
</div>
#wrapper {display:table;}
#cell {display:table-cell; vertical-align:middle;}

The Goods

  • The content can dynamically change height (doesn’t have to be defined in CSS)
  • Content doesn’t get cut off when there isn’t enough room in the wrapper

The Bads

  • Doesn’t work in Internet Explorer (not even the IE 8 beta)
  • Lots of nested tags (not really that bad, this is a subjective topic)

Method 2

This method will use an absolutely positioned div, which has the top set to 50% and the top margin set to negative half the height of the content. This means the object must have a fixed height, that is defined by CSS.

Because it has a fixed height, you may want to set overflow:auto; to the content div, so if there is too much content to fit in, a scrollbar will appear, instead of the content continuing on outside the div!

&lt;div id="content"&gt;
	Content Here		
&lt;/div&gt;
#content {position:absolute; top:50%; height:240px; margin-top:-120px; /* negative half of the height */}

The Goods

  • Works in all browsers
  • Doesn’t require nested tags

The Bads

  • When there isn’t enough space, the content disappears (such as when the div is inside the body and the user shrinks the browser window, a scrollbar will not appear)

Method 3

In this method, we will insert a div above the content element. This will be set to height:50%; and margin-bottom:-contentheight;. The content will then clear the float and end up in the middle.

<div id="floater">
<div id="content">
	Content here
</div>
</div>
#floater	{float:left; height:50%; margin-bottom:-120px;}
#content	{clear:both; height:240px; position:relative;}

The Goods

  • Works in all browsers
  • When there isn’t enough space (ie. the window shrinks) our content will not be cut off, and a scrollbar will appear.

The Bads

  • Only one I can think of is that it requires an extra empty element (which isn’t that bad, another subjective topic)

Method 4

This method uses a position:absolute; div with a fixed width and height. The div is then told to stretch to top:0; bottom:0;. It can’t because of the fixed height, so margin:auto; will make it sit in the middle. This is similar to using the very common margin:0 auto; to horizontally centre block elements.

<div id="content">
	Content here
</div>
#content {position:absolute; top:0; bottom:0; left:0; right:0;
			margin:auto; height:240px; width:70%;}

The Goods

  • Easy

The Bads

  • Doesn’t work in Internet Explorer (does work in IE8 Beta)
  • Content is cut off without scrollbar if there isn’t enough room in the container

Method 5

This method will only centre a single line of text. Simply set the line-height to the height of the object, and the text sits in the middle

<div id="content">
	Content here
</div>
#content {height:100px; line-height:100px;}

The Goods

  • Works in all browsers
  • Doesn’t get cut off when the isn’t enough space

The Bads

  • Only works on text (no block elements)
  • When there is more than a single line (like when it wraps), it breaks badly

This method is very useful on small elements, such as to centre the text inside a button or single-line text field.

Which Method?

My favourite method is number 3 — using a floater and clearing the content. It doesn’t have any major downsides. Because the content will clear:both;, you can also put other elements above it, and when the windows collapses, the centered content will not cover them up. See the demo.

<div id="top">
	<h1>Title</h1>
</div>
<div id="floater"></div>
<div id="content">
	Content Here		
</div>
#floater	{float:left; height:50%; margin-bottom:-120px;}
#top		{float:right; width:100%; text-align:center;}</strong>
#content	{clear:both; height:240px; position:relative;}

Now you know how it works, let’s start creating a simple but interesting website! The final product will look something like this:

Step 1

It’s always good to start with semantic markup. This is how our page will be structured:

  • #floater (to push the content into the middle)
  • #centred (the centre box)
    • #side
      • #logo
      • #nav (unordered list <ul>)
    • #content
  • #bottom (for copyright, etc.)

Here is the xhtml code I will be using:

<!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>A Centred Company</title>
	<link rel="stylesheet" href="styles.css" type="text/css" media="all" />
</head>
 
<body>
	<div id="floater"></div>
	<div id="centered">
 
		<div id="side">
			<div id="logo"><strong><span>A</span> Company</strong></div>
			<ul id="nav">
				<li><a href="#">Home</a></li>
				<li><a href="#">Products</a></li>
				<li><a href="#">Blog</a></li>
				<li><a href="#">Contact</a></li>
				<li><a href="#">About</a></li>
			</ul>
		</div>
 
		<div id="content">
 
			<h1>Page Title</h1>
 
			<p>
			Holisticly re-engineer value-added outsourcing after process-centric collaboration and idea-sharing. 
			Energistically simplify impactful niche markets via enabled imperatives. 
			Holisticly predominate premium innovation after compelling scenarios. 
			Seamlessly recaptiualize high standards in human capital with leading-edge manufactured products. 
			Distinctively syndicate standards compliant schemas before robust vortals. 
			Uniquely recaptiualize leveraged web-readiness vis-a-vis out-of-the-box information. 
			</p>
 
			<h2>Heading 2</h2>
 
			<p>
			Efficiently embrace customized web-readiness rather than customer directed processes. 
			Assertively grow cross-platform imperatives vis-a-vis proactive technologies. 
			Conveniently empower multidisciplinary meta-services without enterprise-wide interfaces. 
			Conveniently streamline competitive strategic theme areas with focused e-markets. 
			Phosfluorescently syndicate world-class communities vis-a-vis value-added markets. 
			Appropriately reinvent holistic services before robust e-services. 
			</p>
 
		</div>
 
	</div>
 
	<div id="bottom">
		<p>
			Copyright notice goes here
		</p>
	</div>
</body>
</html>

Step 2

Now we will start with some basic CSS to lay out the page. You should put this in styles.css, which is linked to at the top of our html.

html, body {
	margin:0; padding:0;
	height:100%;
}
 
body {
	background:url('page_bg.jpg') 50% 50% no-repeat #FC3;
	font-family:Georgia, Times, serifs;
}
 
#floater {
	position:relative; float:left;
	height:50%;	margin-bottom:-200px;
	width:1px;
}
 
#centered {
	position:relative; clear:left;
	height:400px; width:80%; max-width:800px; min-width:400px;
	margin:0 auto;
	background:#fff;
	border:4px solid #666;
}
 
#bottom {
	position:absolute;
	bottom:0; right:0;
}
 
#nav {
	position:absolute; left:0; top:0; bottom:0; right:70%;
	padding:20px; margin:10px;
}
 
#content {
	position:absolute; left:30%; right:0; top:0; bottom:0;
	overflow:auto; height:340px;
	padding:20px; margin:10px;
}

Before we can make our content vertically centred, the body and html must be stretched to 100% height. Because the height is inside the padding and margin, we have to make them 0 so a scrollbar doesn’t appear just to show you a little margin.

The floater’s margin-bottom is half of the content’s height (400px), which is -200px.

You should now have something that looks like this:

The width of #centered is 80%. This is to make your site small on small screens and wide on bigger screens (on my medium-large screen, many old websites are small in the top left corner, and it is a little annoying). This is known as having a liquid layout. min-width and max-width are also set to stop it getting too big or too small. Internet Explorer doen’t support min & max widtgh though. Obviously, you may choose to have a fixed width instead.

Because #centered is position:relative, we can use use absolute positioning inside it to position the elements. overflow:auto; was used on #content, so a scrollbar will appear when the content doesn’t fit inside it. Internet Explorer doesn’t like overflow:auto; unless we tell it the height (not just top and bottom position, and not in %) so we did that as well.

Step 3

The last thing to do is add some more styles to make it look a bit nicer. Lets start with the menu.

#nav ul {
	list-style:none;
	padding:0; margin:20px 0 0 0; text-indent:0;
}
 
#nav li {
	padding:0; margin:3px;
}
 
#nav li a {
	display:block; background-color:#e8e8e8;
	padding:7px; margin:0;
	text-decoration:none; color:#000;
	border-bottom:1px solid #bbb;
	text-align:right;
}
 
#nav li a::after {
	content:'»'; color:#aaa; font-weight:bold;
	display:inline; float:right;
	margin:0 2px 0 5px;
}
 
#nav li a:hover, #nav li a:focus {
	background:#f8f8f8;
	border-bottom-color:#777;
}
 
#nav li a:hover::after {
	margin:0 0 0 7px; color:#f93;
}
 
#nav li a:active {
	padding:8px 7px 6px 7px;
}

The first thing to do when turning a list into a menu kind of thing is to remove the dot points with list-style:none and all the margin and padding. If you want it to have a margin or padding, make sure you specify exactly what, don’t leave it to the web browsers defaults because they can vary.

The next thing to notice is that the links are set to display as a block element. This makes them fill the entire line and gives you more control over them. If you want to make your menu go horizontally (doesn’t work in this design), then you can make them float as well.

The other interesting thing to notice about the menu is the :before and :after CSS pseudo-element let you insert content before and after elements. This is a good way to include little icons or characters such as the arrow at the end of each link. This doesn’t work in Internet Explorer before version 8 though.

Step 4

The last thing to do is add some more CSS to make the page look a bit nicer.

#centered {
	-webkit-border-radius:8px; -moz-border-radius:8px; border-radius:8px;
}
 
h1, h2, h3, h4, h5, h6 {
	font-family:Helvetica, Arial, sans-serif;
	font-weight:normal; color:#666;
}
 
h1 {
	color:#f93; border-bottom:1px solid #ddd;
	letter-spacing:-0.05em; font-weight:bold;
	margin-top:0; padding-top:0;
}
 
 
#bottom {
	padding:10px;
	font-size:0.7em;
	color:#f03;
}
 
 
#logo {
	font-size:2em; text-align:center;
	color:#999;
}
 
#logo strong {
	font-weight:normal;
}
 
#logo span {
	display:block;
	font-size:4em; line-height:0.7em;
	color:#666;
}
 
p, h2, h3 {
	line-height:1.6em;
}
 
a {
	color:#f03;
}

A thing to notice is the rounded corners on #centered. In CSS3, there should be a border-radius property to set the radius of rounded corners. This is not implemented by any major browsers yet, unless you use the -moz or -webkit prefixes (for Mozilla Firefox and Safari/Webkit)

Compatibility Notes

As you might have guessed, Internet Explorer is the only main browser which gives you trouble:

  • The #floater must have a width defined, or it doesn’t do anything in any version of IE
  • IE 6 has too much space around our menu, which breaks it
  • IE 8 has extra space above the

More Ideas

There are many interesting things you can do with centered websites. I used this idea in my redesign of the SWFObject Generator 2.0 (to generate code to use SWFObject 2.0). Here is also another idea.

Sources

I did not discover all this myself. Here are some of the articles I have read which describe some of these techniques: (If you are interested, I recommend you read them)


90

Comments
  • Douglas says:

    Oops, got the greater thans and less thans the wrong way round.

    Should look like this: <div id=”wrapper”> </div>

  • Chris says:

    This is an awesome post! Why isn’t this on Nettuts?

  • Gcyrillus says:

    hello,

    i have myself selected 5 ways to center-align , a whole page , or jus part of a content , i dropped a couple of technics (absolute/relative , float ) .

    First of all , the table one cell remains the only one solid way to do it , then , display:table , display:inline-block and auto margin with absolute positionning .

    It’s only my point of view , i do not say one is better than another one and in the end i keep :
    the table
    display:inline-block
    absolute auto-margin.

    For each of these test , i keep IE in the run , with CC .
    i present this here : yidille.free.fr/plux/valign/?10-5-pistes-pour-centrer-en-xy-vos-pages
    it is in french , but CSS is worldwild , look at the style within the templates :)

    the link to the 5 html templates : yidille.free.fr/plux/valign/?10-5-pistes-pour-centrer-en-xy-vos-pages#bas

    Then , the choice of one or another way will be
    fluid content or
    content with a fixed height ?

    GC
    P.S. , sorry , it’s in french but i hope it brings some more tips to you

  • Aalaap Ghag says:

    Fantastic post. Bookmarking this right now!

  • Ingo Chao says:

    This thread http://csscreator.com/node/16105 discusses a method by Bruno Fassino. I’ve been using it for years since its stable.

  • Banhawi says:

    Nice one , Thanks .

  • Kate says:

    I Just popped in via a list of links from WSG,

    Trying to learn this complicated stuff prior to building a site for a friend. I followed to the letter your tutorial.

    Why a scroll bar in the box Internet Explorer 7 but not not in firefox?

    ..rrolls eyes

    Thanks – nice tutorial and another great link from WSG!

  • Nick Rinylo says:

    Thanks, i find my self giving vertical objects fixed heights and tend to use the horizontal align more often. Would you only specifically need vertical alignment on a liquid site? The I find the best method for aligning a horizontally is margin: 0 auto; although it is important to remember that the needs a width in order for this to work.

    Nick

  • CSS_hack says:

    Your Solution #3 BLOWS!!!

    If you add an image, the top of the image is at the center of the page. I want the image itself to be centered!!

    Anybody know how? thanks anyway.

  • You could also use a drop shadow effect with -webkit-box-shadow: 0px 0px 5px #555 by example to improve visual effect ;)

  • Ausammy says:

    You could always try this… it auto sizes height without any height specification. Only gets a little bit tricky when you float an element inside, but it’s an easy fix.

    css
    ————————

    #wrap {
    background: #CCC;
    width: 500px;
    margin: 0 auto 0 auto;
    }

    ————————

    html
    ————————

    Lorem ipsum dolor sit amet, consectetur adipiscing elit.

    ————————

  • ausammy says:

    I’ll try again :)

    You could always try this… it auto sizes height without any height specification. Only gets a little bit tricky when you float an element inside, but it’s an easy fix.

    css
    ——————
    #wrap {
    background: #CCC;
    width: 500px;
    margin: 0 auto 0 auto;
    }

    html
    ——————
    <div id=”wrap”>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque lobortis massa. Nunc id velit quis massa rutrum facilisis.
    </p>
    </div>

  • Matt says:

    I have been attempting to solve this problem for years with pure CSS. There still seems to be no realistic solution that does not include fixed height containers and elements. I commend you on your efforts and published work on ideas, but it would still seem that tables or javascript are the only solutions that work given variable element heights.

  • Michael says:

    To center a div in CSS would it not be just as easy to use {margin-left:auto; margin-right:auto;} ? That is what I always do.

  • xapU7 says:

    thank for useful info!

  • gazduire web says:

    thank you and keep up the good work!!

  • Linke says:

    Good tips…

    Actually, I tried to do the 3rd method, but it doesnt worked …

    so… I´ve to try changing the HTML structure instead to other one that has a EMPTY DIV, as you said (on the bad side), but didnt apply on the HTML code example …

    - content-

    onlyt this … and will work successfully! :D

    thank you … keep posting..

    Linke.

  • Daniel says:

    Great tutorial, thanks!

  • Paul says:

    I discovered another way to pull this off using just percentages. It uses a wrapper and a container of a given height/width, then uses some percentage math to position it square in the middle of the window. Worth a quick look.

    http://www.sitecrafting.com/blog/to-center-div/

  • Mik says:

    Hi, i’m trying both methods 3 and 4 , and no one works! Even the proposed demo http://douglasheriot.com/tutorials/css_vertical_centre/demo5.html does not work!
    I’m on Firefox 3.0.10.
    What is my mistake??

  • des says:

    awesome!
    exactly what i’ve been looking for for a long time!

  • mikk says:

    Sorry but I have to agree with the table peeps this time, especially if you have an image next to dynamic text (and that text could be one line or multiple). Often this also means height is not available. I have searched all over for the golden fix to this, but nothing really works outstanding. The ones that I can get to work have so many hacks and oddities about them, I feel like it would take an hour to explain to the next designer working on the site about what I did.

  • g says:

    faking a table to get vertical alignment, HILARIOUS! but it works :)

  • Ali says:

    Thank you for this very helpful article! (once again)

  • Anil says:

    Nice article, very helpful, i was desperatly looking for a center align code, but most of them came with javascript which i was not keen to use, thanks once again.

  • DeadlyFishy says:

    I thought this was updated, but I guess not. I copied everything exactly how it is here just to see what it looks like, and it turns out like this – http://webdevelopersstudio.com/tests/blog-themeforest-net-tutorials-vertical-centering-with-css.html – only I have ? instead of the >> thing for some reason on my actual tester.

  • Thanks for the great ideas, and I’m glad they work for many people, but, sorry, I couldn’t get this to work.

    I tried your centering in a simple test case on FF3 and IE7 (see below). Content was rendered about 30% from top, flush left.

    I tried the padding suggestion too, but that failed. I guess I’ll have to go back to good old tables. At least I can hide all those required tags using PHP variables.

    I don’t usually have success with published CSS tips for some reason. I hate experimenting to get it right, but that’s what I usually end up doing.

    My test case is http://www.springtimesoftware.com/temp-center.html. Maybe I made a mistake?

  • There are many sites like this, claiming to have CSS fixes for simple layout problems, but then not working for some browser or another, followed by endless “fixes” that rarely fix the problems completely.

    I HIGHLY recommend http://matthewjamestaylor.com/blog, which has wonderful multi-platform, multi-version, multi-browser solutions to a variety of real-life layout problems (centered tabs or menus, stacked fixed-width boxes that always fit in the window, the “holy grail” (standard three column layout), footers and headers), both liquid and fixed-width and/or fixed-height, all using only pure CSS, without even a single {display:table}. And there is much more there, besides. The author, who is primarily an artist, has produced a very logical, elegant, nestable, and functional set of techniques that deserve some consideration.

    Enjoy!

  • Benedikt says:

    Thank you for this article.

    “Sample pages are not working any more!”

  • Nice article, I’ve used all the methods

  • Odd says:

    Quick solution: Use a Table.

    I know, I know… using a table for us css designers is like asking us to swim in a pool of horse manure, but, you can always rely on a table to keep your food below your chin.

    Al diggy

  • M Hussain says:

    Thanks for useful article.

  • panco says:

    This is really a great tutorial. But I got a question is that why there’s a float:left ? I have deleted it and it didn’t make any difference. I’m confused.
    THX.

  • julie day says:

    @mark rushworth
    this is xhtml STRICT and by far the sexiest way of accomplishing vertical centering #3 is frumpy in comparison lol:

    #sexycontainer{
    right: 50%;
    bottom: 50%;
    position:absolute;
    }
    #containersexy {
    left: 50%;
    top: 50%;
    position: relative;
    }

  • Edgar says:

    I have use this on my website.. but it don’t work in IE7

    (Method 3)

  • Edgar says:

    *My English isn’t very good*

  • Jesse says:

    @edgar you need to set the width:1px; on the floater for it to work in ie7.

  • ammar hassan says:

    Nice, and thanks a lot…. got here through smashing magazine dot com