0

.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.

happy_story
  • 1
  • 1
  • 7
  • 17
  • 1
    I am preparing a detailed answer, stay tuned ;) – Temani Afif Oct 28 '20 at 21:46
  • @TemaniAfif I hope you can do better than me! – disinfor Oct 28 '20 at 21:50
  • @disinfor It will tackle it from another angle, let's hope he will get the idea ;) – Temani Afif Oct 28 '20 at 22:13
  • The answer to your final question on Temani's answer that's been moved to chat is that it's undefined. As a result, different browsers may put the baseline in different positions. – Alohci Oct 30 '20 at 12:20
  • @Alohci Thanks. The baseline seems to change all the time depending on the vertical-alignment of the elements inside. If i have two elements, one larger than the other, setting the larger one to vertical align top seemingly moves the baseline up because the other elements being aligned middle moves up with it, but setting the align to bottom completely changes the baseline again. I can't find a pattern. Anyway, can i ask you something - do you know how all this works? If yes, how do you know this? Do you still remember it from the first time you studied, or do you just read it & understand it? – happy_story Oct 30 '20 at 12:51
  • Yes, I know how it works. And Temani explained it very thoroughly. But no, I didn't just read and understand it. I revisited vertical alignment many times over several years and gradually pieced together an understanding of it all directly from the CSS 2.1 specification. Vertical alignment is, in my opinion, the most esoteric and non-intuitive aspect in all of CSS. If you do get your head round it, you'll understand it better than 99% of all web devs. So I do encourage you to set aside notions of "pushed-down" in favour of "aligned-with" and re-read what Temani told you. – Alohci Oct 30 '20 at 13:10
  • I think i already understood it. The most important thing to understand is the order in which child-elements get rendered in, and that the height is defined after the alignment. This helps understand the direction in which the parent has to expand to contain the larger element. Knowing that the side of expansion changes was the key to understanding how it works. No offense to Tamani, but his explanation is not good at all. I can explain this to anyone with ease & i know they will understand it 100%. The key is understanding what exactly do people not get, not forcing different ways on them. – happy_story Oct 30 '20 at 13:26

2 Answers2

1

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>
disinfor
  • 10,865
  • 2
  • 33
  • 44
  • I am sorry, i can't understand your examples. I understand that the baseline is pushed down because of the margin, but i don't understand how does that explain why does the second line-box moves up when i set the vertical-align top to the first one? I can't picture what is happening in my mind. If i set the vertical align baseline to the second box, it just stays where it is, since it's placed at the baseline. I really don't understand what does the baseline being pushed down has to do with the second box moving up when vertical align is set to the first one? Can u please try & dumb it down? – happy_story Oct 28 '20 at 18:45
  • I am also not sure if your example demonstrates something that i am not understanding. Could you please try and separate your examples so it's easier to follow? – happy_story Oct 28 '20 at 18:46
  • @Ihatecontrolfreaks added comments. It's really simple: you have margin on an `inline-block` element and not the other. If no `vertical-align` property is set on EITHER element - the *baseline of the line* (both elements) is set to the bottom of the element WITH MARGIN. As soon as you add `vertical-align` to EITHER element, you change how the vertical align is computed - because `inline-block` elements sit on the same relative line. I think you might be thinking they are separate elements that don't affect each other, but that is not the case. – disinfor Oct 28 '20 at 19:00
  • Well, yes, i understand that the margin changes how the vertical-align works, since the margin of the first box pushes down both boxes, and it creates more space inside, but again, i don't understand why does setting the vertical-align top to the first box, which obviously has no space to move, results in the second box being pushed up? This has to do with the lack of space inside, but i don't understand what exactly causes the second box to move up? – happy_story Oct 28 '20 at 19:36
  • Again, you are thinking that the two boxes as separate entities when **they are not** in the context of the baseline. – disinfor Oct 28 '20 at 19:37
  • _which obviously has no space to move, results in the second box being pushed up?_ This is where you are getting it wrong. When you change the `vertical-align` of any of the `inline-block` elements, you are changing how the **whole** line computes the vertical alignment compared to the baseline. The first box **is** vertical aligned to the top, but as you see, you won't notice it happening because of the margin. – disinfor Oct 28 '20 at 19:40
  • Well, they are separate entities, are they not? They are just both positioned at the same baseline inside the line-box container. Since they are both line-boxes too. So when the first box has margin, it expands the container, and the baseline is pushed down. But how does that explain why adding vertical-align top to the first box results in the second being pushed up? If you for example add 100px margin to the second box, now you will have space for the first one to move up, and it will, but then if you add vertical-align top to the second box, the first one moves up! Why!? – happy_story Oct 28 '20 at 19:43
  • Are you saying that vertical-align changes the baseline of the container line-box? That is not the case. Vertical-align allows you to align a line-box INSIDE another line-box container. Or is it that, you are saying that if you have two or more than one line-box inside a line-box container, then changing the vertical-align to one of the line-boxes results in all of them being changed? That is not what it says here: https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align – happy_story Oct 28 '20 at 19:48
  • I just tested few things, and if you remove all the margins, and instead set vertical-align sub or text-top to the second box, the first one does not move, only the second gets aligned. So doesn't that prove that they work separately? Doesn't that prove that i am vertically aligning individual line-boxes inside their parent, and not the line-box of the parent itself? – happy_story Oct 28 '20 at 20:12
  • @Ihatecontrolfreaks no, take a look at my edited example. The last container has an arbitrary value. Since I set the `vertical-align: 10px` that means the baseline shifts to accommodate the change. I also made a simple `span` version. – disinfor Oct 28 '20 at 20:19
  • well in your example, only the 'var' box moves up, while the other two remain as they are? So.. doesn't that reinforce what i said, which is that, each individual box is aligned separately? Otherwise, all 3 boxes would've moved up when you set the 'var' box to 10px. – happy_story Oct 28 '20 at 20:53
  • Also, i wish you would've separated your examples in different snippets so it's more easy to follow what is happening. It's difficult to follow when you have 10 different examples cramped inside a single snippet and a large outcome screen. – happy_story Oct 28 '20 at 20:56
  • You're asking for free help. – disinfor Oct 28 '20 at 21:13
  • 1
    I appreciate your help, and i don't mean to sound ungrateful. I just really want to understand this, and i'm getting annoyed that i can't, and the MDN doesn't explain it either. – happy_story Oct 28 '20 at 21:31
1

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?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/223848/discussion-on-answer-by-temani-afif-why-does-the-sibling-line-box-gets-aligned-v). – Samuel Liew Oct 30 '20 at 03:02