My usual approach to vertically center text is to use line-height equal to the container's height.
Thus, the container has
height: 60px;
line-height: 60px;
and the child elements have
line-height: 60px;
That works. But if you increase the font-size
above 1em, that messes it up. Worse, browsers are inconsistent in how they do it!
Here's a JSFiddle demo: http://jsfiddle.net/tgv2rx7f/7/. Notice that in Firefox the big "A." is too close to the top of the container. It doesn't look so bad in the demo, but on my actual website it's very noticeable and distracting. If you fix it in Firefox, then it's too low in Chrome.
I can't seem to get this to work consistently no matter what I do. I've played with different vertical-align
values, top
, text-top
, middle
... no dice. I can get it to work if I change the container to display:inline
, but in my layout it needs to be block
or inline-block
.
PS, I can't use flex box.
Edit: this is what I'm seeing, both in my actual webpage (blue) and in the JSFiddle (green).
Chrome:
Firefox:
Edit 2: Thanks to andyb
for pointing out the fact that using em
s will change the size of a container set with px
. It also helped bring to light another complication, namely that browsers treat font sizes and heights differently, but that seemed beyond the scope of this question, so I created a new question on that topic (here) and marked andyb
's answer as accepted.
On both the container
and b
block the line-height
and font-size
cause the height of the block to change. line-height
and font-size
interact with each other! line-height
is the vertical distance between the lines of text in a container. So with line-height:60px
and font-size:2.5em
the height of the container grows to 73px. This is countered in CSS by your hard height:60px
on the container but what this does not do is affect the text baseline. The text "1." in the container will move up or down if the baseline changes. If the font-size on the .a
is increased the baseline drops, dragging the text "1." down. You can check this by turning all all vertical alignment and increasing the font-size of .a
and the "1." content moves down. With this in mind, we should really only need to fix the container's vertical alignment, like this:
.container {
display: block;
overflow: hidden;
height: 60px;
line-height: 60px;
vertical-align: top;
font-size: 2.5em;
width: 100%;
text-align: center;
background-color: lightgreen;
text-decoration: none;
}
.a {
font-size: 2em;
}
<a href="#" class="container">
1.<span class="a">A.</span><span class="b">b b b b b b b</span>
</a>
But the baseline is still where the bottom of the A
is since the A
is the last container in normal flow, see:
And as long as the .b
font-size is less than .a
then the baseline will stay with .a
, see next image with small font-size on .b
:
However, notice that the .b
container has inherited the line-height:60px
- see Why does this inline-block element have content that is not vertically aligned, so the height is correct, and we can vertical-align
the .b
to the top of the container which is the same height and therefore result in the text being middle aligned, like so:
.container {
display: block;
overflow: hidden;
height: 60px;
line-height: 60px;
vertical-align: top;
font-size: 2.5em;
width: 100%;
text-align: center;
background-color: lightgreen;
text-decoration: none;
}
.a {
font-size: 2em;
}
.b {
display: inline-block;
font-size: 23px;
vertical-align: top;
font-family: sans-serif;
text-align: center;
}
<a href="#" class="container">
1.<span class="a">A.</span><span class="b">b b b b b b b</span>
</a>