Jared Zhou
Jared Zhou

Reputation: 51

Nested inline element 'vertical-align' behaves different on Chrome and Firefox

I put a span element inside a span, and set vertical-align: 20px for the outer span and vertical-align: top for the inner span. HTML and CSS code is here. codepen

.mid {
  vertical-align: 20px;
  outline: 1px solid;
}

.right {
  vertical-align: top;
    outline: 1px solid;
}

.se {
  vertical-align: top;
}
<html>

<body>
  <p class="out">A<span class="mid">B<span class="right">C</span>D</span><span class="se">E</span></p>

</body>

</html>

On Chrome, it shows

enter image description here

On Firefox, it shows

enter image description here

Which is the standard behaviour?

Upvotes: 2

Views: 103

Answers (1)

Temani Afif
Temani Afif

Reputation: 272592

If we follow the specification describing line boxes we can read:

As described in the section on inline formatting contexts, user agents flow inline-level boxes into a vertical stack of line boxes. 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.
  3. The line box height is the distance between the uppermost box top and the lowermost box bottom. (This includes the strut, as explained under 'line-height' below.)

In Chrome the element is clearly outside its line box so it sounds like a bug for me. If we add border we can clearly see the overflow:

.mid {
  vertical-align: 20px;
  outline: 1px solid;
}

.right {
  vertical-align: top;
    outline: 1px solid;
}

.se {
  vertical-align: top;
}

p {
  border:2px solid red;
}
<html>

<body>
  <p class="out">A<span class="mid">B<span class="right">C</span>D</span><span class="se">E</span></p>

</body>

</html>

Another intresting result if you set vertical-align:-20px

.mid {
  vertical-align: -20px;
  outline: 1px solid;
}

.right {
  vertical-align: top;
  outline: 1px solid;
}

.se {
  vertical-align: top;
}

p {
  border:2px solid red;
}
<html>

<body>
  <p class="out">A<span class="mid">B<span class="right">C</span>D</span><span class="se">E</span></p>

</body>

</html>

Firefox will make the C element to stick to the top of the p which is the logical result. Chrome will again do things differently and I think it's also a bug.


Worth to note that if you make the mid element inline-block you will have a consistant behavior since the alignment is easier and both browsers and C will now consider the line box inside mid and will always stick to its top

.mid {
  vertical-align: -20px;
  outline: 1px solid;
  display:inline-block;
}

.right {
  vertical-align: top;
  outline: 1px solid;
}

.se {
  vertical-align: top;
}

p {
  border:2px solid red;
}
<p class="out">A<span class="mid">B<span class="right">C</span>D</span><span class="se">E</span></p>

<p class="out">A<span class="mid" style="vertical-align: 20px">B<span class="right">C</span>D</span><span class="se">E</span></p>


Well, it seems that there is a logical explanation to what chrome is doing if we follow the exmaple below

.mid {
  outline: 1px solid;
}

.right {
  vertical-align: top;
  outline: 1px solid;
}

.se {
  vertical-align: 40px;
}

p {
  border: 2px solid red;
  display: inline-block;
}
<p class="out">A<span class="mid" style="vertical-align:baseline">B<span class="right">C</span>D</span><span class="se">E</span></p>

<p class="out">A<span class="mid" style="vertical-align: 20px;">B<span class="right">C</span>D</span><span class="se">E</span></p>

<p class="out">A<span class="mid" style="vertical-align: 40px">B<span class="right">C</span>D</span><span class="se">E</span></p>

<p class="out">A<span class="mid" style="vertical-align:-20px">B<span class="right">C</span>D</span><span class="se">E</span></p>

It seems that chrome is first placing the C element at the top (considering a default baseline alignment to mid) then aligning the mid element which create the strange result. The C is shifted by the pixel value set to vertical-align of .mid element from the top.

Upvotes: 2

Related Questions