How to vertically center text in a block elment wi

2019-07-04 06:38发布

问题:

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 ems 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.

回答1:

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>