Why vertically aligned text shows up lower and lower inside of <span> or <a>?

A usual way to vertically centered some inline text or image is

#one-div { font: 16px/16px Verdana, Arial, sans-serif }
#one-div * { vertical-align: middle }

with the HTML of

<div id="one-div">
    hello <span>world</span> try <a href="http://www.google.com">more</a> <span><span><span>see</span></span></span>
</div>

see sample at: http://jsfiddle.net/934Zu/2/

It can be compared to: http://jsfiddle.net/934Zu/1/

This is an example how they are vertically centered: http://jsfiddle.net/934Zu/6/

Why are elements inside of <span> or <a> go lower and lower? The <span> doesn’t have padding or margin or border, so no vertical space should be there.

What is a way to fix it so that the line of text (and images, if inside <span> and/or <a>) can be vertically aligned perfectly? (other than putting everything in the same level of nested <span> or <a>, which might not be a totally elegant fix)

Is this what you are trying to do?

You need to have the v-align middle boxes adjoining another inline element in order for them all to v-align.

I added in an <em> and a <b> tag and wrapped everything in a <p> for a BG color.

thanks for trying it…
though, if made bigger size, they are not vertically centered:

Last time I saw someone with code like this, what happened there was that the tags inside the div had their own line-height and vertical align etc, while the “loose” text around them only had what they inherited directly from the div.

That person’s problem was solved by having all inline content inside some kind of tag… all the tags themselves matched up. That is, they all had to be the same “level”.

The first example code has “see” heavily nested… each nesting has its own vertical-align within its parent tags (and lots and lots of parent tags there).

So I’d say the only “safe” way to do vertical-align is something like


<div id="one-div">
    <span>hello</span> <span class="s">world</span><span>try</span> <a href="http://www.google.com">more</a> <span class="ss">see</span>
</div>

Here, everyone is
div->span
If it were a tree, all the spans are at the same level.

Scroll down this page a bit to see the boxes that the spans and the words themselves (as “anonymous inline boxes” according to the specs) are built. You see they have more space around them than what you’d think.

yes… if hopefully, there is a solution without needing to have the same level of nested <span> or <a>… because otherwise, what if a word needs to be linked and so there is an extra level of <a>, so all other elements will need to add a dummy layer of <span> to them.

As long as your text is adjoining other inline boxes with the same line-height then they will v-center. It looks like “anonymous inline boxes” will also v-center fine in the case of all line-heights being the same.

It is the line-heights that are keeping all the “defined boxes” at v-center. The div * {vertical-align:middle;} rule below is effecting the “anonymous boxes”, if you change it to top or bottom you will see them take effect.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Vertical-Aligning Text</title>

<style type="text/css">
div {
    margin:50px auto 0;
    background:#CDF;
    text-align:center;
}
div * {vertical-align:middle;}

b {
    font:30px/36px arial;
    background:lime;
}
span {
    font:24px/36px arial;
    background:yellow;
}
em {
    font:18px/36px arial;
    background:orange;
}

</style>

</head>
<body>

<div>
    anonymous <b>30px/36px text</b> anonymous <span>24px/36px text</span> <em>18px/36px text</em> <b>30px/36px text</b> 
</div>

</body>
</html>