Case in point: Vertical centering with pseudo-elements

Today, IN an article, I accidentally saw a method to achieve vertical centralization using pseudo-elements, and I spent a lot of effort to understand its principle, so I have this article.

Add a pseudo-element with 100% height vertical-align: middle to the parent element and the code looks like this:

<div class="parent">
  <div class="child">child</div>
</div>
Copy the code
.parent {
    width: 300px;
    height: 300px;
    border: 1px solid red;
    text-align: center;
}
.child {
    background: blue;
    width: 100px;
    height: 40px;
    display: inline-block;
    vertical-align: middle;
}
.parent::before {
    content: ' ';
    height: 100%;
    display: inline-block;
    vertical-align: middle;            
}
Copy the code

The basic concept

Before we dive in, let’s understand some basic concepts.

Base element

In a row of inline elements, the element with the highest row height is taken as the reference element.

Baseline for inline elements

As we all know, the vertical alignment of inline elements is baseline alignment by default. The base line refers to the lower edge of the letter “x” :

Image source: https://blog.csdn.net/lulujiajiawenwen/article/details/8245201

For example, the two inline elements in the figure below are baseline aligned, with the red line as their baseline:

<div class="parent">
  <div class="child1">abcxyz</div>
  <div class="child2">efghij</div>
</div>
Copy the code
.parent {
  width: 300px;
  height: 100px;
  border: 1px solid blue;
}
.child1 {
  display: inline-block;
  height: 20px;
  background-color: green;
}
.child2 {
  display: inline-block;
  height: 20px;
  background-color: yellow;
}
Copy the code

The vertical alignment of inline elements depends on the vertical-align attribute

How do inline elements determine vertical alignment? Is based on the vertical-align attribute. This attribute defines the vertical alignment of the baseline of the element in the row relative to the baseline of the element in the row. The default value is baseline.

Insight into the

Distinguish the line element baseline from the line element baseline

Again, the concept of vertical-align: this attribute defines the vertical alignment of the baseline of an element in a row relative to the baseline of the element in the row. Here are two phrases: what is the “baseline of inline elements”? What is the “baseline of the element’s row”?

Without a doubt, the “line element baseline” is what we call it in the baseline: the lower edge of the letter “X”. We write an “X” in an element, and its bottom line is the element’s baseline.

As you can see, there is a space between the base line of the element and the base line of the element (above, between the “X” and the red bottom), which is reserved for letters like “G” and “J” or Chinese characters

So what is the “baseline of the element’s row”? In a nutshell: the line on which the reference element of the row is aligned. We treat this element’s row as the parent element, which indicates that the parent element’s baseline is determined by one of its children, the base element, and that the base element’s baseline is determined by the line on which the base element is aligned.

This is where we understand the difference between the two “baselines” :

  • The baseline of an inline element is its own attribute. When the element has no child elements but only text, the bottom edge of the letter “x” is taken
  • The baseline of the parent element of the inline element is derived from one of its children, the baseline element, which is the line on which the parent element is aligned

That is, if the base element is aligned with a center line, the baseline of the row is the center line of the base element. If the base element is aligned with a top line, the baseline of the row is the top line of the base element.

Look again at the basis and process of vertical alignment

With that in mind, let’s go back to this statement: by default, the vertical alignment of inline elements is baseline alignment. How does this explain the vertical alignment of the following two elements?

.parent {
  width: 300px;
  height: 100px;
  border: 1px solid blue;
}
.child1 {
  display: inline-block;
  width: 50px;
  height: 100%;
  background-color: green;
}
.child2 {
  display: inline-block;
  width: 50px;
  height: 20px;
  background-color: yellow;
}
Copy the code

One might say, this is easy, neither element has vertical-align, so by default, they are aligned at baseline, so the text inside is aligned along the red line.

What’s wrong with this sentence? The mistake is both. The correct procedure would be to align the base elements with their own baseline and the rest of the inline elements with their parent’s baseline:

  1. The parent element first determines the base element, the highest elementchild1
  2. child1vertical-alignProperty defaults tobaseline, so it aligns its own baseline — as the base element, the position does not change, but it affects the parent element’s baseline position
  3. So the base line of the parent element ischild1The baseline
  4. child2vertical-alignProperty defaults tobaselineSo its vertical alignment is also “baseline alignment”
  5. But the most important thing is this:child2Align to the parent element’s baseline, not your own, i.e.,child2Aligns the baseline of the parent element

Seems like there’s no difference between the two explanations, right? Why do we have to go through all this trouble to go through alignment? Now let’s add vertical-align: middle to child1.

Yi? Add vertical-align: middle to child1; ! Child2: vertical-align: middle

It is much easier to analyze it again as we did before:

  1. The parent element first determines the base element, the highest elementchild1
  2. child1This time thevertical-align: middleCenter line alignment – As the base element, the position does not change, but it affects the base position of the parent element
  3. So the baseline of the parent element is the midline of Child1
  4. child2vertical-alignProperty defaults tobaselineSo its vertical alignment is also “baseline alignment”
  5. child2It’s aligned to the parent’s baseline, so it’sIts baseline has to be alignedchild1The center line

So again, is child2 really centered vertically? The answer is no. Since we say “the baseline of child2 is aligned with the midline of child1”, child2 is not vertically centered, but a little higher in the middle.

Now add vertical-align: middle to child2 and it will drop a little, so it is truly vertically centered:

Let’s look at the process again:

  1. The first three steps are the same: the base of the parent element ischild1The center line
  2. child2vertical-alignProperties formiddle, using center line alignment, soIts center line aligns the parent element’s baselineOr, equivalent to its midline alignmentchild1The center line

conclusion

At this point, you should have a good understanding of how browsers implement vertical alignment. You can change the vertical-align attribute of child1 and child2 to other values (sup, top,… See what happens and try to explain why using the procedure above.

  1. The parent element’s baseline === of the base elementvertical-alignProperty corresponding to the line
  2. Each inline element will be itselfvertical-alignThe line corresponding to the attribute is aligned to the parent element’s baseline

Principle of case

The insertion position of the pseudo-element

First, before pseudo-elements are rendered before all children of the parent element, and after pseudo-elements are inserted after all children of the parent element. That is, pseudo-elements and child elements are siblings.

The principle of

Going back to our case at the beginning of this article, the principle is clear: use content: “; Height: 100% Yields a pseudo-element with a width of 0, that is, it is not displayed; It’s 100% high, so it’s the highest, and it’s the base element of the row; Use vertical-align: middle to set the base line of the parent element to the center line of the pseudo-element, and then align the other elements in the line with the center line. The pseudo-element has a height of 100%, so its center line is the center line of the entire parent element, which enables the other inline elements to be vertically centered.

My guess about the underlying principle

From the perspective of compilation principles, I understand the above process as follows:

When a browser parses CSS, for an inline element:

  • If the inline element does not have any children, that is, only text or an image, then itsvertical-alignA property is aIntrinsic properties
  • The baseline of the parent element of this inline element is oneThe comprehensive propertiesIt first finds the highest child element of all its children and then takes itsvertical-alignThe line corresponding to the property acts as its own baseline

Then align all of the inline elements to the parent element’s baseline by virtue of the vertical-align attribute.

This also explains why when you set the vertical-align attribute of the base element, the base element position is unchanged, because the parent element’s baseline is already based on its vertical-align attribute value. Right

conclusion

The above is my understanding of vertical-align and baseline. Welcome your criticism and correction.