Setting the blocks to display: none
and then adding display: inline-block
is a way of getting around the problem, but doesn't fix the problem itself.
The main issue is the vertical-align
property set on the block
class. By default, this is set to baseline
. Before your button is clicked, all your divs are lined up in a row, invisible, with their baseline set to the bottom of the div. However, when the button is clicked, not only do your blocks become visible, but more crucially, you add some text inside the div. This changes the baseline, making it the bottom of the text within the div instead. However, because of vertical-align: baseline
, the baselines of all the divs in the row try to align. The baseline of the visible divs with text has to align with the baseline of the invisible divs with no text. But their baselines are now different, so the only way they can all sit in a straight line on their baselines would be if the divs with text are pushed down.
I've simplified your snippets to show you what I mean. I've made the divs visible, removed the button, and instead, have manually added some text into your divs in html. As you can see, for the divs with text, the bottom of the text aligns with the bottom of the div without text.
body {
background: white;
}
.block {
display: inline-block;
width: 100px;
height: 140px;
border: 2px solid;
}
<html>
<body>
<div class="block">TEXT</div>
<div class="block">TEXT</div>
<div class="block"></div>
<div class="block">TEXT</div>
</body>
</html>
The reason why changing the blocks to display: none
in the beginning, and then displaying them one by one works is because in this case, there is never a point when textless divs and divs with text are present in the DOM at the same time, so there is never a mismatch of baselines. The divs enter the DOM with text in them, and so their baselines always match up. However, this doesn't entirely fix the issue. If the text in the divs were of different lengths, for instance, the bottom of the multiline text would match up with the bottom of the single-line text, resulting in misalignment once again.
Example:
body {
background: white;
}
.block {
display: inline-block;
width: 100px;
height: 140px;
border: 2px solid;
}
<html>
<body>
<div class="block">text</div>
<div class="block">text</div>
<div class="block">very long text which takes up more than one line</div>
<div class="block">text</div>
</body>
</html>
So the proper fix for this would be to add vertical-align: top
to the block
class, to make sure that our alignment doesn't jump all over the place in response to the changing baseline.