How does the vertical-align property work?

The easiest way to understand why it's not working it to add many line of text because vertical-align will align on the respective line (the line-box) and not the whole container like you may think.

So if we add more text we have the following.

#outer {
  box-sizing: border-box;
  border: red 1px solid;
  height: 200px;
  text-align: center;
}

#inner {
  border: blue 1px solid;
  height: 200px;
  width:180px;
  display: inline-block;
  overflow:hidden;
}

.header {
  display: inline;
  border: green 1px solid;
  margin: 0;
}
<div id="outer">
  <div id="inner">
    <h1 class="header">
      Some Text Some Text Some Text
    </h1>
  </div>
  <div id="inner">
    <h1 class="header" style="vertical-align:middle;">
      Some Text Some Text Some Text
    </h1>
  </div>
  <div id="inner">
    <h1 class="header" style="vertical-align:top;">
      Some Text Some Text Some Text
    </h1>
  </div>
</div>

Basically nothing to align and all the alignments are almost equivalent simply because the text is defining the line-box thus its height is equal to the height of the line box and there is no room for alignment.

Now let's increase the height of the line (using line-height)

#outer {
  box-sizing: border-box;
  border: red 1px solid;
  height: 200px;
  text-align: center;
}

#inner {
  border: blue 1px solid;
  height: 200px;
  width:180px;
  line-height:200px;
  display: inline-block;
}

.header {
  display: inline;
  border: green 1px solid;
  margin: 0;
  line-height:1em;
}
<div id="outer">
  <div id="inner">
    <h1 class="header">
      Some Text Some Text Some Text
    </h1>
  </div>
  <div id="inner">
    <h1 class="header" style="vertical-align:middle;">
      Some Text Some Text Some Text
    </h1>
  </div>
  <div id="inner">
    <h1 class="header" style="vertical-align:top;">
      Some Text Some Text Some Text
    </h1>
  </div>
</div>

See how each line is now bigger and each text is aligned on its respective line that has a height of 200px and we can clearly see how the alignment are different.

In this case, the text has enough room to be aligned like you want and we see the magic if we keep only one line of text:

#outer {
  box-sizing: border-box;
  border: red 1px solid;
  height: 200px;
  text-align: center;
}

#inner {
  border: blue 1px solid;
  height: 200px;
  line-height: 200px;
  display: inline-block;
}

.header {
  display: inline;
  border: green 1px solid;
  margin: 0;
  line-height:1em;
}
<div id="outer">
  <div id="inner">
    <h1 class="header">
      Some Text
    </h1>
    <h1 class="header" style="vertical-align:middle">
      Some Text
    </h1>
    <h1 class="header" style="vertical-align:top">
      Some Text
    </h1>
    <h1 class="header" style="vertical-align:bottom">
      Some Text
    </h1>
  </div>
</div>

You may also note how middle and baseline are very close because:

Aligns the middle of the element with the baseline plus half the x-height of the parentref

There is only a half x-height of difference.

Another important fact to note is that if we don't set a line height to the inline element this one will inherit the line-height of his parent and alignment like top won't have any effect.

#outer {
  box-sizing: border-box;
  border: red 1px solid;
  height: 200px;
  text-align: center;
}

#inner {
  border: blue 1px solid;
  height: 200px;
  line-height: 200px;
  display: inline-block;
}

.header {
  display: inline;
  border: green 1px solid;
  margin: 0;
}
<div id="outer">
  <div id="inner">
    <h1 class="header">
      Some Text
    </h1>
    <h1 class="header" style="vertical-align:middle">
      Some Text
    </h1>
    <h1 class="header" style="vertical-align:top">
      Some Text
    </h1>
  </div>
</div>

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

Having the same line-height means that the element is already at the top and also the bottom of the line box so both top bottom will behave like baseline (the default value).


The height of the line-box can also be controled by the height of elements. You may have a big font-size for one element that will make the height of the line bigger and have enough room to align small texts next to it in the same line box:

#outer {
  box-sizing: border-box;
  border: red 1px solid;
  height: 200px;
  text-align: center;
}

#inner {
  border: blue 1px solid;
  height: 200px;
  display: inline-block;
}

.header {
  display: inline;
  border: green 1px solid;
  margin: 0;
}
@keyframes change {
  from {font-size:20px;}
  to {font-size:100px;}
}
<div id="outer">
  <div id="inner">
    <h1 class="header">
      Text
    </h1>
    <h1 class="header" style="font-size:100px;animation:change 5s linear alternate infinite">
      T
    </h1>
    <h1 class="header" style="vertical-align:middle;">
      Text
    </h1>
    <h1 class="header" style="vertical-align:top;">
      Text
    </h1>
    <h1 class="header" style="vertical-align:bottom;">
      Text
    </h1>
  </div>
</div>

You can also constrol the line box by setting height of inline-block element:

#outer {
  box-sizing: border-box;
  border: red 1px solid;
  height: 200px;
  text-align: center;
}

#inner {
  border: blue 1px solid;
  height: 200px;
  display: inline-block;
}

.header {
  display: inline;
  border: green 1px solid;
  margin: 0;
}
.elem {
 display:inline-block;
 background:red;
 width:2px;
 height:5px;
 animation:change 5s linear alternate infinite;
}
@keyframes change {
  from {height:20px;}
  to {height:100px;}
}
<div id="outer">
  <div id="inner">
    <h1 class="header">
      Text
    </h1>
    <div class="elem">
    </div>
    <h1 class="header" style="vertical-align:middle;">
      Text
    </h1>
    <h1 class="header" style="vertical-align:top;">
      Text
    </h1>
    <h1 class="header" style="vertical-align:bottom;">
      Text
    </h1>
  </div>
</div>

As a conclusion: to align using vertical-align you should have a line box that has a height bigger enough (explicitely set or set by other elements) where you can align your element. If your element is defining the line-box (which is the common case) then there is nothing to align.


Some good questions to have more detais:

Vertical align not working on inline-block

Inline elements and line-height

My inline-block elements are not lining up properly

Why is this inline-block element pushed downward?