Vertical-Align Misuse

Saturday, January 21, 2006 by Nicholas Gagne

I have written a follow-up to this article demonstating how to center one element inside of another element: Applied CSS Vertical-Align. Specifically for dynamically generated elements with various dimensions.

It seems that many people do not have a full understanding of the vertical-align property. Anyone who has seen any reference to this CSS property would have probably guessed what it is supposed to do. Unfortunately many people use it incorrectly, and wonder why it's not working like it should.

If you apply the text-align property to a container such as a div, the child elements would be horizontally aligned. So, if you apply the vertical-align property to a container, all of those child elements should be vertically aligned, right? Wrong. The only case where it would work like that is if you apply the vertical-align property to a table cell (td). For everything else, we will need to find out how the vertical-align property really works.

First, let's check the W3C's definition:

Applies to: inline-level and 'table-cell' elements

This property affects the vertical positioning inside a line box of the boxes generated by an inline-level element.

Don't feel bad if you find the second part of the definition hard to grasp. Fortunately, the first part of the definition gives us some insight on how to use the vertical-align property. We already know this works on table cells, so we can set that aside. The fact that it only applies to inline-level element will quickly eliminate some of the confusion, so don't even bother trying to vertically align block-level elements with the vertical-align property. What the second part of the definition is trying to say, in conjunction with the first part, is that the vertical-align property must be applied to the inline-level element that is a child of another element.

An example of this could be a div with 3 img elements inside and you want them to be vertically centered, you wouldn't apply the vertical-align property to the div itself, but instead apply it to each of the 3 img elements within the div. The CSS could look similar to this:

div img {
    vertical-align: middle
}

If you had various kinds of inline-level elements inside of a container, (such as img, span, or other inline-level elements) instead of applying the vertical-align property to each of the child elements, you could apply it to all of the elements within that div in one shot:

div * {
    vertical-align: middle
}

To help you get started on the road to proper vertical-allign use, here is a list of all of the values, taken from the W3C, for the vertical-align property:

  • Baseline: Aligns the baseline of the element with the baseline of the parent element. If the element doesn't have a baseline, align the bottom margin edge with the parent's baseline.
    vertical-align: baseline
  • Middle: Aligns the vertical midpoint of the element with the baseline of the parent element plus half the x-height of the parent.
    vertical-align: middle
  • Sub: Lowers the baseline of the element to the proper position for subscripts of the parent element. (Note: this value has no effect on the font size of the element's text).
    vertical-align: sub
  • Super: Raises the baseline of the element to the proper position for superscripts of the parent element. (Note: This value has no effect on the font size of the element's text).
    vertical-align: super
  • Text-top: Aligns the top of the element with the top of the parent's content area, which is determined by the font size.
    vertical-align: text-top
  • Text-bottom: Aligns the bottom of the element with the bottom of the parent's content area, which is determined by the font size.
    vertical-align: text-bottom
  • <percentage>: Raises (positive value) or lowers (negative value) the element by this distance (a percentage of the 'line-height' value). A value of '0' means the same as 'baseline'.
    vertical-align: 100%
  • <length>: Raises (positive value) or lowers (negative value) the element by this distance. A value of '0' means the same as 'baseline'.
    vertical-align: 30px

The top and bottom properties can be slightly tricky in the way that the position of top and bottom may change if the element has vertically aligned childeren. Here is what the W3C has to say about the top and bottom values:

[top and bottom] align the element relative to the line box. Since the element may have children aligned relative to it (which in turn may have descendants aligned relative to them), these values use the bounds of the aligned subtree. The aligned subtree of an inline element contains that element and the aligned subtrees of all children inline elements whose computed 'vertical-align' value is not 'top' or 'bottom'. The top of the aligned subtree is the highest of the tops of the boxes in the subtree, and the bottom is analogous.

  • Top: Aligns the top of the aligned subtree with the top of the line box.
  • Bottom: Aligns the bottom of the aligned subtree with the bottom of the line box.

For most situations you probably won't have nested vertically aligned elements, so the top and bottom values would act more like this:

  • Top: Aligns the top of the element with the top of the parent element.
    vertical-align: top
  • Bottom: Aligns the bottom of the element with the bottom of the parent element.
    vertical-align: bottom

Aside from using the vertical-align property on table cells there are of course some browser inconsistencies (Internet Explorer). Have a look at this excellent Web browser CSS support table for more information.

Update: per Nick Watts' request I have added an example page using all of the vertical-align property's values. View the Text-Align sample page to see this CSS property in action. If you view this example page in different browsers (IE and Firefox for example), it will be easy to see the rendering inconsistencies.