happy_story
happy_story

Reputation: 1155

Why does the sibling line-box gets aligned vertically whenever there is no space for the first line-box to be vertically aligned?

.container {
  border: 1px solid;
  height:200px;
}

.first {
  display: inline-block;
  font-size: 30px;
  background-color: darkcyan;
  border: 1px solid;
  margin:50px 0 0 0;
}

.second {
  display: inline-block;
  border: 1px solid;
  background-color: red;
  font-size:30px;
  margin:0;
}
<div class="container">


    <div class="first">Lorem ipsum</div>  


    <p class="second">Lorem ipsum</p>

</div>

Now, in this example, i have increased the margin of the first line-box on purpose. Because the margin is increased, both line-boxes are pushed down thus creating space inside the container line-box.

Now, if i apply 'vertical-align' to the second line-box, it moves without a problem, since there is plenty of space. However, obviously there is no space for the first line-box to move up or down, but when i apply vertical-align to it, the second line-box moves almost as if the vertical align properties applies to it.

Example:

.container {
  border: 1px solid;
  height:200px;
}

.first {
  display: inline-block;
  font-size: 30px;
  background-color: darkcyan;
  border: 1px solid;
  margin:50px 0 0 0;
  vertical-align: top;
}

.second {
  display: inline-block;
  border: 1px solid;
  background-color: red;
  font-size:30px;
  margin:0;
}
<div class="container">


    <div class="first">Lorem ipsum</div>  


    <p class="second">Lorem ipsum</p>

</div>

As you can see, i am applying the vertical-align to the first line-box, but instead the second one gets vertically aligned.

Like i said, i understand why the first one would not get aligned, since there is no space for it to move up, but what i can't understand is, why does the second line-box gets vertically aligned on top? I know this has something to do with the fact that the first one cannot move, but i cannot understand what exactly is happening here.

Upvotes: 0

Views: 140

Answers (2)

Temani Afif
Temani Afif

Reputation: 272909

Now, if i apply 'vertical-align' to the second line-box, it moves without a problem, since there is plenty of space. However, obviously there is no space for the first line-box to move up or down, but when i apply vertical-align to it, the second line-box moves almost as if the vertical align properties applies to it.

Your missunderstanding is in the plenty of space or let's say space in general. Vertical align will not consider the space you have in mind but will create that space.

let's first understand the definition

This property affects the vertical positioning inside a line box of the boxes generated by an inline-level element. ref

Then you can read the following rules:

The height of a line box is determined as follows:

  1. The height of each inline-level box in the line box is calculated. For replaced elements, inline-block elements, and inline-table elements, this is the height of their margin box; for inline boxes, this is their 'line-height'.

  2. The inline-level boxes are aligned vertically according to their 'vertical-align' property. In case they are aligned 'top' or 'bottom', they must be aligned so as to minimize the line box height. If such boxes are tall enough, there are multiple solutions and CSS 2.1 does not define the position of the line box's baseline (i.e., the position of the strut, see below).

  3. The line box height is the distance between the uppermost box top and the lowermost box bottom.

We first start by defining the height of each element and we consider the margin box then we place all the elements and only at end the line box height is defined (the spaces you are talking about).

In your first example, both element have a default baseline alignment

Align the baseline of the box with the baseline of the parent box. If the box does not have a baseline, align the bottom margin edge with the parent's baseline.

so both will get aligned by their text and logically the margin of any of them will push the other.

A better example with different fonts:

.container {
  border: 1px solid;
  background:linear-gradient(blue,blue) 0 78px/100% 2px no-repeat;
}

.first {
  display: inline-block;
  font-size: 30px;
  background-color: darkcyan;
  border: 1px solid;
  margin: 50px 0 0 0;
  opacity:0.5;
}

.second {
  display: inline-block;
  border: 1px solid;
  background-color: red;
  font-size: 50px;
  margin:0;
  opacity:0.5;
}
<div class="container">
  text outside

  <div class="first">Lorem ipsum</div>


  <p class="second">Lorem ipsum</p>

</div>

As you can see we have an alignment by text and after we made the alignment we place our element and we should respect the margin. Imagine that you need to first glue both element sconsidering their text then you need to place the whole puzzle inside.

Now if you apply vertical-align:top to your first element and you keep baseline (the default one) for the other you will have:

Align the top of the aligned subtree with the top of the line box

Our element need to be aligned to the top considering its margin box AND will no more participate to the baseline alignment so the other element will no more follow the first one. It's like we fired the first element for the baseline group since now it will be using the top alignment thus we get the following

.container {
  border: 1px solid;
  background:linear-gradient(blue,blue) 0 48px/100% 2px no-repeat;
}

.first {
  display: inline-block;
  font-size: 30px;
  background-color: darkcyan;
  opacity:0.5;
  border: 1px solid;
  margin: 60px 0 0 0;
  vertical-align:top;
}

.second {
  display: inline-block;
  border: 1px solid;
  background-color: red;
  font-size: 50px;
  margin:0;
  opacity:0.5;
}
<div class="container">
  text outside

  <div class="first">Lorem ipsum</div>


  <p class="second">Lorem ipsum</p>

</div>

with different font-size to better see the trick:

.container {
  border: 1px solid;
  background:linear-gradient(blue,blue) 0 48px/100% 2px no-repeat;
  font-size: 50px;
}

.first {
  display: inline-block;
  font-size: 30px;
  background-color: darkcyan;
  opacity:0.5;
  border: 1px solid;
  margin: 60px 0 0 0;
  vertical-align:top;
}

.second {
  display: inline-block;
  border: 1px solid;
  background-color: red;
  font-size: 20px;
  margin:0;
  opacity:0.5;
}
<div class="container">
  text outside

  <div class="first">Lorem ipsum</div>


  <p class="second">Lorem ipsum</p>

</div>

So it's not about enough space or not but how to place element considering other elements. In this last case, the first element is set alone at the top (we are done with it). The second element will be set to the baseline alignment and we only have the outside text that will follow it. The margin of the first one will have no effect since it's no more considered in the baseline alignment.

Some related question for more details and examples:

Vertical-align aligns everything else except self

https://stackoverflow.com/a/54190413/8620333

Why is the descender “created” when baseline is set to vertical-align?

Why does vertical-align: text-top make element go down?

Upvotes: 1

disinfor
disinfor

Reputation: 11533

Think of it this way: when you set margin-top on any element on the same line, you are essentially changing where the baseline is computed.

When you have two inline-block elements - one with top margin - like your first example, that block is now setting the new baseline

Once you set the vertical-align on any element on your line, you've now changed how the elements sit on the horizontal line - regardless of margin, because the margin is part of the inline-block element.

.container {
  border: 1px solid;
  height: 200px;
}

.first {
  display: inline-block;
  font-size: 30px;
  background-color: darkcyan;
  border: 1px solid;
  margin: 50px 0 0 0;
  vertical-align: top;
}

.first2 {
  display: inline-block;
  font-size: 30px;
  background-color: darkcyan;
  border: 1px solid;
  margin: 50px 0 0 0;
  vertical-align: bottom;
}

.first3 {
  display: inline-block;
  font-size: 30px;
  background-color: darkcyan;
  border: 1px solid;
  margin: 50px 0 0 0;
  vertical-align: middle;
}

.first4 {
  display: inline-block;
  font-size: 30px;
  background-color: darkcyan;
  border: 1px solid;
  margin: 0;
}

.first5 {
  display: inline-block;
  font-size: 30px;
  background-color: darkcyan;
  border: 1px solid;
  margin: 0;
  vertical-align: top;
}

.first6 {
  display: inline-block;
  font-size: 30px;
  background-color: darkcyan;
  border: 1px solid;
  margin: 0;
}

.second,
.second2,
.second3,
.second4,
.second5,
.second6 {
  display: inline-block;
  border: 1px solid;
  background-color: red;
  font-size: 30px;
  margin: 0;
}

.second4 {
  margin-top: 30px;
  vertical-align: top;
}

.second5 {
  margin-top: 30px;
}

.second6 {
  vertical-align: 10px;
}

.va {
  vertical-align: 20px;
}
<div class="container">
  <!-- MARGIN-TOP:50px, VERTICAL ALIGN: TOP -->
  <div class="first">Lorem ipsum</div>
  <!-- NO MARGIN, NO VERTICAL ALIGN -->
  <p class="second">Lorem ipsum</p>
</div>


<div class="container">
  <!-- FIRST: MARGIN-TOP:50px, VERTICAL ALIGN: BOTTOM -->
  <div class="first2">Lorem ipsum</div>
  <!-- NO MARGIN, NO VERTICAL ALIGN -->
  <p class="second2">Lorem ipsum</p>
</div>

<div class="container">
  <!-- FIRST: MARGIN-TOP:50px, VERTICAL ALIGN: MIDDLE -->
  <div class="first3">Lorem ipsum</div>
  <!-- NO MARGIN, NO VERTICAL ALIGN -->
  <p class="second3">Lorem ipsum</p>
</div>


<div class="container">
  <!-- FIRST: NO MARGIN, NO VERTICAL ALIGN -->
  <div class="first4">Lorem ipsum</div>
  <!-- MARGIN-TOP: 30px, VERTICAL-ALIGN: TOP -->
  <p class="second4">Lorem ipsum</p>
</div>

<div class="container">
  <!-- FIRST: NO MARGIN, VERTICAL-ALIGN: TOP -->
  <div class="first5">Lorem ipsum</div>
  <!-- MARGIN-TOP: 30px, NO VERTICAL ALIGN -->
  <p class="second5">Lorem ipsum</p>
</div>

<div class="container">
  <!-- NO MARGIN, NO VERTICAL ALIGN -->
  <div class="first6">Lorem ipsum</div>
  <!-- NO MARGIN, ARBITRAY VERTICAL ALIGN VALUE -->
  <p class="second6">Lorem ipsum</p>
</div>

<div class="container">
  <span>baseline element</span>
  <span class="va">vertical</span>
  <span>baseline element</span>
</div>

.container {
  border: 1px solid;
  height: 200px;
}

.first {
  display: inline-block;
  font-size: 30px;
  background-color: darkcyan;
  border: 1px solid;
  margin: 0;
  
}

.second {
  display: inline-block;
  border: 1px solid;
  background-color: red;
  font-size: 30px;
  margin: 30px 0 0 0;
  vertical-align: top;
}

.third {
  display: inline-block;
  border: 1px solid;
  background-color: red;
  font-size: 30px;
  margin: 0;
}
<div class="container">
  <!-- FIRST: NO MARGIN, NO VERTICAL ALIGN  -->
  <div class="first">Lorem ipsum</div>
  <!-- MARGIN-TOP: 30px, VERTICAL-ALIGN: TOP-->
  <p class="second">Lorem ipsum</p>
  <!-- MARGIN-TOP: 0, NO VERTICAL ALIGN -->
  <p class="third">Lorem ipsum</p>
</div>

Upvotes: 1

Related Questions