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:
- The parent element first determines the base element, the highest element
child1
child1
的vertical-align
Property 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- So the base line of the parent element is
child1
The baseline child2
的vertical-align
Property defaults tobaseline
So its vertical alignment is also “baseline alignment”- But the most important thing is this:
child2
是Align to the parent element’s baseline, not your own, i.e.,child2
Aligns 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:
- The parent element first determines the base element, the highest element
child1
child1
This time thevertical-align: middle
Center line alignment – As the base element, the position does not change, but it affects the base position of the parent element- So the baseline of the parent element is the midline of Child1
child2
的vertical-align
Property defaults tobaseline
So its vertical alignment is also “baseline alignment”child2
It’s aligned to the parent’s baseline, so it’sIts baseline has to be alignedchild1
The 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:
- The first three steps are the same: the base of the parent element is
child1
The center line child2
的vertical-align
Properties formiddle
, using center line alignment, soIts center line aligns the parent element’s baselineOr, equivalent to its midline alignmentchild1
The 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.
- The parent element’s baseline === of the base element
vertical-align
Property corresponding to the line - Each inline element will be itself
vertical-align
The 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 its
vertical-align
A 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 its
vertical-align
The 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.