I agree that this is an unexpected behavior of vertical-align: middle and is probably responsible for a ton of vertical alignment hacks to work around the resulting visual artifacts. I too would have also expected that vertical-align: middle would by default align to the middle of the capital letters rather than the lower case or that there would at least be an alternate property like vertical-align: capital-middle or similar. But no such luck.
For reference: Mozilla Developer Network vertical-align: middle documentation.
The example in your question is unfortunately a little overly complicated to demonstrate the underlying problem. A more obvious demonstration of the problem is when you try to align the center line of an image with the center line through the capital letters of some neighboring text (as follows). I hope that this will help you to extrapolate an answer to your original question.
.imageTextPair {
font-size: 50px;
}
.imageTextPair img {
height: 75px;
vertical-align: middle;
}
<span class="imageTextPair">
<img src="https://www.citypng.com/public/uploads/preview/reticle-crosshair-red-icon-free-png-701751694974301y3cnksxiin.png">
Neighboring text
</span>
As you can see, the middle of the image aligns with the center line through the lower case letters as described by the spec.
I tried solving the capital alignment problem using the new "display: flex" but without any luck. The following is my alternate in development solution using modern day tools:
.imageTextPair {
font-size: 50px;
}
.imageTextPair img {
--imagePixelHeight: 75;
height: calc(var(--imagePixelHeight) * 1px);
vertical-align: calc(0.5cap - ((var(--imagePixelHeight) / 2) * 1px));
}
<span class="imageTextPair">
<img src="https://www.citypng.com/public/uploads/preview/reticle-crosshair-red-icon-free-png-701751694974301y3cnksxiin.png">
Neighboring text
</span>
To explain how this works, the baseline of inline images is by default along the bottom of the image. The vertical-align property can currently take a number value that adjusts this baseline upward or downward. The calculation I perform basically moves the image down from the baseline by half the image height (so the middle of the image aligns with the baseline of the surrounding text), then I move the image upwards by half the height of the capital letters (0.5cap) to align the middle of the image exactly with the middle of the capital letters. This should in theory work with any font because the "cap" unit of measure uses the appropriate metrics inside the font.
You can also do the same thing using font relative units (em) so the image scales with the font if you change the font-size:
.imageTextPair {
font-size: 50px;
}
.imageTextPair img {
--imageEmHeight: 1.2;
height: calc(var(--imageEmHeight) * 1em);
vertical-align: calc(0.5cap - (var(--imageEmHeight) / 2) * 1em);
}
<span class="imageTextPair">
<img src="https://www.citypng.com/public/uploads/preview/reticle-crosshair-red-icon-free-png-701751694974301y3cnksxiin.png">
Neighboring text
</span>
The obvious drawback of this approach is that you need to the know and set the height of the image explicitly in both the height and vertical-align properties. It would obviously be much nicer if we could implicitly use the height of the corresponding image in our vertical-align calculations. If anybody has some ideas of how this might be accomplished (without using JavaScript) I would welcome some further refinement to this approach.