3

I was trying to understand how vertical-align works. In Understanding vertical-align, or "How (Not) To Vertically Center Content", it had an example with a <p> that contained a <span style="display: inline-block; vertical-align: middle"> and it looked like I'd expect it to.

I messed around, and I did this:

p {
  background: yellow
}

span {
  display: inline-block;
  vertical-align: middle;
  height: 50px;
  background: pink;
}
<p>
    Hello <span>What in the</span> World?
</p>

...but I didn't expect that result (run the snippet to see). Why is it that after applying vertical-align only to the <span>, everything else got vertically aligned except the <span> content?

I'm not looking to "fix" anything, but I'd like to understand why this happens. Is this expected behavior, a bug, or something else?

Partik
  • 808
  • 9
  • 15
  • After understanding the answer, I created this fiddle, for anyone else curious about this behavior: http://jsfiddle.net/yawpqr4k/ – Partik Oct 03 '18 at 22:47

2 Answers2

6

Is this expected behavior, a bug, or something else?

Yes it's the expected behavior.

Why is it that after applying vertical-align only to the <span>, everything else got vertically aligned except the <span> content

It's not exactly like that, vertical-align will specify the alignment of the elements and based on that the browser will render the output. So all your element are getting aligned and not only the text like you think.

Let's start by removing the alignment

p {
  background: yellow
}

span {
  display: inline-block;
  height: 50px;
  background: pink;
}
<p>
    Hello <span>What in the</span> World?
</p>

The default alignment is baseline, so the baseline of the inline-block will get aligned with the baseline of its parent p.ref.

And the baseline of inline-block element is defined by the text inside it same thing for the p. To better see this, use a different font-size.

p {
  background: 
    linear-gradient(red,red) 0 22px/100% 1px no-repeat,
    yellow
}

span {
  display: inline-block;
  height: 50px;
  font-size:25px;
  background: 
    linear-gradient(red,red) 0 22px/100% 1px no-repeat,
    pink;
}
<p>
    Hello <span>What in the</span> World?
</p>

You can clearly see that the text inside the inline-block element is at the same line of the text in p.


Now if you add vertical-align:middle you will align the middle of the element with the baseline plus half the x-height of the parent.ref. The middle of the inline-block is simply the middle and the baseline of the parent is like previously based on the text and we simply add the half the x-height. That's why the text is somehow in the middle of the inline-block element:

p {
  background:
   linear-gradient(red,red) 0 calc(50% + 0.5ex) /100% 1px no-repeat, /*the baseline*/
   yellow;
  
}

span {
  display: inline-block;
  height: 100px;
  font-size:25px;
  vertical-align:middle;
  background: 
    linear-gradient(red,red) center/100% 1px no-repeat, /*the middle*/
    pink;
}
<p>
    Hello <span>What in the</span> World?
</p>

As you can see the baseline is slightly miss aligned with the middle because the middle of the element is exaclty aligned with the baseline + half the x-height( 0.5ex)

You can play with different values to see the results.

bottom (Aligns the bottom of the element and its descendants with the bottom of the entire line.)

p {
  background:
   yellow;
  
}

span {
  display: inline-block;
  height: 100px;
  font-size:25px;
  vertical-align:bottom;
  background: 
    pink;
}
<p>
    Hello <span>What in the</span> World?
</p>

top (Aligns the top of the element and its descendants with the top of the entire line.)

p {
  background:
   yellow;
  
}

span {
  display: inline-block;
  height: 100px;
  font-size:25px;
  vertical-align:top;
  background: 
    pink;
}
<p>
    Hello <span>What in the</span> World?
</p>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • 1
    Thank you! So, `vertical-align:middle` doesn't vertically center the inline element's content, it centers the **inline-element**, (or in this case, the pink block). And in order to center a 50px block in a line that is much smaller, the pink block actually had to push the `p`'s height outward so it had room to align it's center with the text's center. This was interesting. I created this fiddle to mess around even further: http://jsfiddle.net/yawpqr4k/ Thanks! – Partik Oct 03 '18 at 22:44
  • @Partik exactly, vertical-align always center the element itself considering the other elements around and the parent and never the content inside it. – Temani Afif Oct 03 '18 at 22:45
  • 1
    @Partik to be more precise the inline-block is inside a line-box, so the height of the line-box is defined by the content inside it and especially heights and alignment of content that's why in some case your inline-block is like pushing the content. So the logic is that we place all the element considering their alignement, we take the upper bound from the top and lower bound from the bottom to define the boundaries of the line-box and in this case your inline-block is controling this – Temani Afif Oct 03 '18 at 22:50
-3

It is not a bug. This is the expected result.

The content inside a block or inline-block element with height set, will be aligned to top.

Felix A J
  • 6,300
  • 2
  • 27
  • 46