Centering Lists

Centering Lists

One of the most common techniques for creating a menu or some sort of a navigational bar is by using a list. A list is well-structured, uses fewer elements to parse than a table (buzzword tableless) and can always fall back to normal HTML when CSS or JavaScript is used to manipulate it for effects. (i.e, degrade gracefully)

This is probably the easiest way to center.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>Centering Lists</title>
<style type="text/css">
* { margin:0; padding:0; }
#nav
{
    text-align:center; /* Not meant for centering a block element */
    padding:10px 0;
    background-color:lightblue;
}
#nav ul
{
    display:inline;
    padding:5px 0 5px 5px;
    background-color:green;
}
#nav ul li
{
    display:inline;
    background-color:yellow;
    margin-right:5px;
}
#nav ul li a
{
    display:inline;
    text-decoration:none;
    color:black;
    padding:0 5px;
}
#nav ul li a:hover
{
    background-color:red;
    color:white;
}
</style>
</head>
<body>
<div id="nav">
<ul>
<li class="first"><a href="#">Menu 1</a></li>
<li><a href="#">Menu 2</a></li>
<li><a href="#">Menu 3</a></li>
<li><a href="#">Menu 4</a></li>
<li class="last"><a href="#">Menu 5</a></li>
</div>
</body>
</html>

But this has some drawbacks.

  • text-align

    is meant for aligning text, not block elements, but this works for centering inline blocks on all browsers. But now, all text nodes within all child blocks inherits this text-align alignment property.

  • height

    Because the list and list items are inline, there is no room for adusting or specifying the height of the menu items. height, padding-top, padding-bottom won’t have any effect.

A workaround for inline is by treating the list as a table and the list items as table-cells. But Internet Explorer supports display:table and display:table-cell only from version 8 onwards. So this is a no no solution for IE 6 & IE 7. See the display declaration

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>Centering Lists</title>
<style type="text/css">
* { margin:0; padding:0; }
#nav
{
    padding:10px 0;
    background-color:lightblue;
}
#nav ul
{
    display:table;
    margin-left:auto;
    margin-right:auto;
    background-color:green;
}
#nav ul li
{
    display:table-cell;
    padding:10px 0 10px 5px;
    background-color:green;
}
#nav ul li.last
{
    padding-right:5px;
}

#nav ul li a
{
    text-decoration:none;
    color:black;
    padding:5px;
    background-color:yellow;
}
#nav ul li a:hover
{
    background-color:red;
    color:white;
}
</style>
</head>
<body>
<div id="nav">
<ul>
<li class="first"><a href="#">Menu 1</a></li>
<li><a href="#">Menu 2</a></li>
<li><a href="#">Menu 3</a></li>
<li><a href="#">Menu 4</a></li>
<li class="last"><a href="#">Menu 5</a></li>
</ul>
</div>
</body>
</html>

A better option would be float the elements and specify exact widths. This works nicely when you know the exact content and can specify the width of each element.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>Centering Lists</title>
<style type="text/css">
* { margin:0; padding:0; }
#nav
{
    padding:10px 0;
    background-color:lightblue;
}
#nav ul
{
    display:block;
    padding:5px 0 5px 5px;
    width:370px; /* 30x4 (width of a) + 125 (width of Menu Item 3) + 5x5 (margin right) + 5x10x2 (padding left & right for a) */
    height:30px;
    margin-left:auto;
    margin-right:auto;
    background-color:green;
}
#nav ul li
{
    display:block;
    float:left;
    margin-right:5px;
    background-color:yellow;
}
#nav ul li a
{
    display:block;
    min-width:30px;
    width:30px;
    line-height:30px; /* Align vertically in the middle */
    text-align:center;
    text-decoration:none;
    color:black;
    padding:0 10px;
}
#nav ul li a:hover
{
    background-color:red;
    color:white;
}
</style>
<!--[if lte IE 7]>
<style type="text/css">
#nav ul li.last
{
    margin-right:0;
}
</style>
<![endif]-->
</head>
<body>
<div id="nav">
<ul>
<li class="first"><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#" style="width:125px;">Menu Item 3</a></li>
<li><a href="#">4</a></li>
<li class="last"><a href="#">5</a></li>
</ul>
</div>
</body>
</html>

For a fully floating list with centering, applying display:inline-block to the list is enough to achieve the desired result. But according to Quirksmode, inline-block is incomplete in IE6 and IE7. I don’t know how incomplete works, but it wierdly seems to work in IE6 when added in IE conditional statements.

<style type="text/css">
#nav-container ul
{
    display:inline-block;
}
</style>
<!--[if lte IE 7]>
<style type="text/css">
#nav-container ul
{
    display:inline; /* For some reason now this works as inline-block in IE6 ?!? */
}
</style>
<![endif]-->

Full HTML :

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>Centering Lists</title>
<style type="text/css">
* { margin:0; padding:0; }
#nav
{
    text-align:center;
    padding:10px 0;
    background-color:lightblue;
}
#nav ul
{
    display:inline-block;
    padding:5px 0 5px 5px;
    background-color:green;
}
#nav ul li
{
    display:block;
    float:left;
    background-color:yellow;
    margin-right:5px;
}
#nav ul li a
{
    display:block;
    min-width:30px; /* Wont work in IE6 */
    line-height:30px; /* Align vertically in the middle */
    text-decoration:none;
    text-align:center;
    color:black;
    padding:0 10px;
}
#nav ul li a:hover
{
    background-color:red;
    color:white;
}
</style>
<!--[if lte IE 7]>
<style type="text/css">
#nav ul
{
    display:inline; /* For some reason now this works as inline-block in IE6 ?!? */
}
#nav ul li.last
{
    margin-right:3px;
}
</style>
<![endif]-->
</head>
<body>
<div id="nav">
<ul>
<li class="first"><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">Menu Item 3</a></li>
<li><a href="#">4</a></li>
<li class="last"><a href="#">5</a></li>
</ul>
</div>
</body>
</html>

And using HTML5’s nav element :

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>Centering Lists</title>
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<script src="http://ie7-js.googlecode.com/svn/version/2.1(beta4)/IE9.js"></script>
<![endif]-->
<style type="text/css">
* { margin:0; padding:0; }
header, section, footer, aside, nav, article, figure { display:block; }
#nav
{
    margin-top:0; /* ie7-js's IE9.js seems to add a margin-top */
    text-align:center;
    padding:10px 0;
    background-color:lightblue;
}
#nav ul
{
    display:inline-block;
    padding:5px 0 5px 5px;
    background-color:green;
}
#nav ul li
{
    display:block;
    float:left;
    margin-right:5px;
    background-color:yellow;
}
#nav ul li a
{
    float:left; /* Required for IE6 */
    display:block;
    min-width:30px;
    line-height:30px; /* Align vertically in the middle */
    text-decoration:none;
    text-align:center;
    color:black;
    padding:0 10px;
}
#nav ul li a:hover
{
    background-color:red;
    color:white;
}
</style>
<!--[if lte IE 7]>
<style type="text/css">
#nav ul
{
    display:inline; /* For some reason this works in IE6 ?!? */
}
#nav ul li.last
{
    margin-right:3px;
}
</style>
<![endif]-->
</head>
<body>
<nav id="nav">
<ul>
<li class="first"><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">Menu Item 3</a></li>
<li><a href="#">4</a></li>
<li class="last"><a href="#">5</a></li>
</ul>
</nav>
</body>
</html>