Understanding CSS’s vertical-align Property

“Vertical-align isn’t working!” cried the web developer.

The vertical-align property is one of those features of CSS that sounds pretty self-explanatory, but can cause problems for CSS beginners. I think even many CSS veterans have had problems figuring this one out at times.

In this post, I’ll try to cover it in an understandable manner.

What it Does Not Do

The common misconception about vertical-align is that, when it’s applied to an element, it will make all the elements inside that element change their vertical position. For example, when using vertical-align: top on an element, it’s assumed that the contents of that element get pushed up to the top of the element.

This reminds me of something we used to do back in the days of table-based layouts:

<td valign="top">
Whatever...
</td>

In the case of this table cell example, the “valign” property (now obsolete in HTML5) would cause the elements inside of it to get pushed to the top of the table cell. So naturally, when CSS developers start using vertical-align, they assume the same thing — that the contents of the elements become aligned in accordance with the property’s value.

But this is not how vertical-align works.

What it Actually Does

The vertical-align property can be broken down into three easy-to-understand steps:

  1. It only applies to inline or inline-block elements
  2. It affects the alignment of the element itself, not its contents (except when applied to table cells)
  3. When it’s applied to a table cell, the alignment affects the cell contents, not the cell itself

In other words, the following code would have no effect:

div {
	vertical-align: middle; /* this won't do anything */
}

Why? Because a <div> is a block-level element, not inline. Of course, if you converted the <div> to an inline or inline-block element, then the vertical-align property would have an effect.

On the other hand, when used correctly (on an inline or inline-block element), the vertical-align property will cause the targeted element to align itself in relation to other inline elements.

How high up or down an element is aligned would depend on the size of the inline elements on the same line, or on the line-height set for that line.

Some Visuals

Here’s a visual demonstration along with explanatory text to help you grasp what’s happening when you vertically align an inline element:

Vertical Align in Action

And here’s a JSBin that has some mixed inline elements with one of them aligned vertically to the top:

Keyword Values

The different keyword values that you can use with vertical-align are:

  • baseline (the default or “initial” value)
  • bottom
  • middle
  • sub
  • super
  • text-bottom
  • text-top
  • top

It’s likely you won’t use many of these, but it’s good to know the variety of choices you have. For example, in the demo page, because the value for vertical-align is set to “top” for the input element, it aligns with the highest element in the line (the big image).

But if you don’t want to align the element in relation to images or other block-like inline elements, then you can instead choose the values text-top or text-bottom, so the element will align in relation to the text on the line.

About the Value “middle”

Update: (Dec. 7/2011) One thing I neglected to explain in the original article (because I didn’t realize it at first) is how the value “middle” works. Thanks to comments by Pablo Botta.

Unfortunately, vertical-align: middle will not align the inline element to the middle of the largest element on the line (as you would expect). Instead, a value of middle will cause the element to be aligned with the middle of a hypothetical lower-case “x” (also called the “x-height”). So, it seems to me that this value should actually be called “text-middle” to correctly identify what it does.

See this demo where I’ve bumped up the font size so that the x-height is much larger. So generally speaking, a value of “middle” won’t be used very often.

Non-Keyword Values

Something you might not be aware of is that vertical-align accepts length and percentage values. So these would all be valid examples:

input {
	vertical-align: 100px;
}

span {
	vertical-align: 50%;
}

img {
	vertical-align: -300px;
}

Although you can read an explanation in the spec describing what the keyword and length values do, I think it’s much more useful to just fiddle with the values yourself and compare different results.

Conclusion

If I can sum up how to use this traditionally misunderstood property in one sentence, I’d say:

The vertical-align property works only on inline or inline-block elements and table cells and when not used on a table cell, it will affect the alignment of the element itself, not the element’s contents.

Update: I guess I was trying to simplify the meaning here, but originally I neglected to mention that when I refer to “inline” elements, this would also include inline-block elements. Thanks to Brian Irish for pointing this out.

Advertise Here

26 Responses

  1. Bob:

    Great article, thanks! I think only one aspect is missing: how to reproduce the functionality most people think of for vertical-align. I.e., how to align all elements within another element?

    • I’ve used display:table-cell on an element, then vertical-align will literally position the contained text top, middle, bottom. Feels like misuse though, and IE < 8 doesn't like it.

  2. It affects the alignment of the element to which it’s applied, not to its content)
    This was the magic sentence! Thanks for that!

    • Cool… And thanks for showing me how awkward that sentence sounded. I’ve modified it a little bit. :)

    • Pablo Botta:

      How is this explain? http://jsfiddle.net/p4bl1t0/JX3hQ/1/
      How is the size of the line calculated?

      • From what I understand, the line’s size is dependent on the size of the largest inline element on that line. For example, in your jsfiddle, the line’s height is larger because of the images, so the “middle” ends up being the middle point of the image.

        So as I explained, you can use “text-bottom” or “text-top” to align it according to text.

        Also, if the line-height changes, then that would decide the height of the line, so the images would only be of secondary importance. Maybe I’ll add a note about that in the article.

        • Pablo Botta:

          But why when I apply the vertical-align to the inline “A” the text doesn’t go to the middle of the line and place in the bottom? See it first line of the fiddle.

          • Ah, I see what you’re asking.

            The short answer is: You can’t really do that.

            It turns out (and this could probably be an article of its own), the value vertical-align: middle will not align the element to the mid-point of other elements, but instead, to the mid-point of a small letter “x” on the line.

            For example, see this demo:

            http://jsbin.com/apiqog/edit#html,live

            Notice I’ve bumped up the font-size for the container element, and now the input is aligned in the center of the element. But it’s still not perfect because it has space above and below that’s not desired (to make room for the hypothetical lower case “g” and uppercase letters).

            Drop an “x” into that container before the “input” element and you’ll see that the input will be aligned to the center of the “x”.

            So, the value of “middle” is more like “text-middle”. I probably should have explained this. I’ll have to try to make an update to add mention of that.

          • Pablo Botta:

            Thank you, Louis!

  3. Andy:

    This is a great tidbit. I never really explored the explanation for vertical-align before and just assumed it should work like the table property. Thanks!

  4. Brian Irish:

    Please keep in mind it’s not JUST inline level elements this applies to, but inline-block level elements as well. In fact, people often have to use the vertical-align:top; property with inline-block level elements to bring them “back to the top”, if you will.

    • Yes, that’s correct! I’ll add that. Thanks.

    • Thanks, Recently I’m working with twitter bootstrap and I have seen they use it in there button like .btn classes . They use inline-block and align it with vertical-align:top;. Pretty awesome. They also use *display:inline; for IE7 support may be.

      The property we are discussing really help us when we use some element need to style display:inline-block;. Some times it also appear with a extra white space by default…..

  5. great article. Would love to see an expansion of the post; covering centering elements vertically in a containing element. Has always been a little tricky for me to figure out.

    Thanks.

  6. Great article – thanks!

  7. Emma:

    Thanks, I can already think of uses for this as I didn’t know about this bit of code – aligning text with logos and that kind of thing. Nice simple explanation – I’m sure it will be really useful and I will be testing it out soon.

  8. Devan D:

    As Daniel S. said, “It affects the alignment of the element to which it’s applied, not to its content.” are the magic words. Good article and examples. Thanks for keeping it simple. I don’t do complicated.

  9. Cool tutorial… I get to learn about it more..!! I have been using vertical-align but your article added value to it….!! Thanks much

  10. Great post ! I so appreciate this site. This is the information I was looking for.

  11. Nightmare:

    height + line-height + verti-align:middle for the win

  12. Ashely:

    Nice article, but CSS vertical-align property with value “middle” won’t work for blocks specially for blocks in IE6-7. But, there is solution: CSS “vertical-align: middle” for all browsers (IE6-7)

  13. Rahul:

    Found this article just when I needed it. Explained in a very easy-to-understand way. My questions about vertical-align got answered. Thanks

  14. Thanks for putting this article up. May be a small step for a human being, but it is a huge contribution to human kind.

  15. Great article, thanks for posting. In my case inline-block wasn’t working, but when I switched it to table-cell “vertical-align” did what I wanted it to do. I feel like I’m implementing it incorrectly since the data isn’t setup as a data table. Either way your article opened my eyes to the bigger picture of vertical-align. Thanks.

  16. Basically it’s quite good stuff. But how about vertical alignment of an input-field text-type? Is there any possibility to stick the text to the bottom of the field no matter which height it has?

    Greets, Ronny

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field. If you use keywords, your comment will be deleted, or your name will be replaced with the alias from your email address. No foul language, please. Thank you for cooperating.

Instructions for code snippets: Wrap inline code in <code> tags; wrap blocks of code in <pre> and <code> tags. When you want your HTML to display on the page in a code snippet inside of <code> tags, make sure you use &lt; and &gt; instead of < and >, otherwise your code will be eaten by pink unicorns.