Horizontal + Vertical Centering of element of Unknown height


At last… an opportunity to spend some quality time blogging 🙂 . I’ve had some very positive feedback from my previous blogs which is always nice and motivates you to write more. Well, today I wanted to nail a long standing issue with positioning blocks of text in the center of containing elements.

It all started when a customer rang me and said they wanted the text in their menu items wrapped. They were already centered using #menu { line-height: 70px; text-align: center; }, but this method breaks if you need to wrap lines, because both lines become 70px high. So… what should I do? Tell the customer that wrapping text is just too hard?!

Firstly, why not use a good old html table to align the content? Well, I tried that, and yes it works, but it didn’t give me the desired results. The problem is I want my <a> element to occupy the entire cell region and the inline text to be centered. A table can be used to center the <a> element, but then it won’t occupy the whole cell.

The W3C actually has a good example of centering blocks using CSS on their website [1], but naturally it doesn’t work in Microsoft Internet Explorer. To be honest though, I don’t really blame IE for this – the lack of clear support for vertical alignment in the CSS spec is a major problem! The spec defines how vertical-align applies to table cells and inline elements only. Most of us are looking for the behaviour described for table cells, but it can’t be used on block elements such as <div> and <p>.

The standards-based solution, which works in Firefox, is to use display: table and display: table-cell in conjunction with the vertical-align. It means you need at least two elements:

<a href="." style="display: table; width: 300px; height: 300px;">
  <span style="display: table-cell; text-align: center; vertical-align: middle;">
    Hello standards<br/>world

To get things to behave in IE, I used absolute positioning with a javascript expression to center the span vertically:

<a href="." style="display: block; position: relative; width: 300px; height: 300px;">
  <span style="display: block; position: absolute; left: 0px; width: 100%;
      text-align: center; cursor: pointer;
      top: expression(this.parentElement.clientHeight / 2 - this.clientHeight / 2);">
    Hello Microsoft<br/>world

View an example of each of these solutions on one page.

The results can be merged using some css hacks (the star hacks are used to target both IE6 and IE7), and the stylesheet looks something like this:

a {
  display: table;
  text-align: center;
  width: 300px;
  height: 300px;
  *display: block;
  *position: relative;

a span {
  display: table-cell;
  vertical-align: middle;
  *display: block;
  *position: absolute;
  *text-align: center;
  *left: 0px;
  *width: 100%;
  *cursor: pointer;
  *top: expression(this.parentElement.clientHeight / 2 - this.clientHeight / 2);

View an example of the cross-browser solution.

This method works for me, but I don’t particularly like the mess it leaves behind. Perhaps things will improve with CSS3… but somehow I doubt it.


[1] http://www.w3.org/Style/Examples/007/center



Posted on June 22, 2008, in Web Dev and tagged . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: