“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:
- It only applies to inline or inline-block elements
- It affects the alignment of the element itself, not its contents (except when applied to table cells)
- 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:
And here’s a JS Bin 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”
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.
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.
“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. :)
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.
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.
Thank you, Louis!
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!
Please keep in mind it’s not JUST
inline
level elements this applies to, butinline-block
level elements as well. In fact, people often have to use thevertical-align:top;
property withinline-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 useinline-block
and align it withvertical-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…..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.
Great article – thanks!
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.
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.
Cool tutorial… I get to learn about it more..!! I have been using vertical-align but your article added value to it….!! Thanks much
Great post ! I so appreciate this site. This is the information I was looking for.
height + line-height + verti-align:middle for the win
Nice Tutorial. Thanks.
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)
Found this article just when I needed it. Explained in a very easy-to-understand way. My questions about vertical-align got answered. Thanks
Thanks for putting this article up. May be a small step for a human being, but it is a huge contribution to human kind.
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.
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
I’ve recently digged deeper into this topic because some times I couldn’t get vertical-align to behave. It resulted in this detailed article why vertical-align does what it does: http://christopheraue.net/2014/03/05/vertical-align/.
Finally understood how to use this property ! Thanks for this article :)
It’s really informative and wonderful article, thanks for sharing..
Very thorough and elegant explaination. Thanx a lot
Thanks for this clear explanation. You saved my day!
Great Article.Thanks for sharing this information
it is very useful , thanks a lot