Margin-top and padding-top set percentage issues

We all know that CSS is simple. So in the peacetime development, also did not care about some specific details. We know roughly what a property value means. For example, we know that CSS box model is composed of margin, border, padding and content. If we want to set the margin of an element, we just set the margin value.

Margin can be a value, percentage, or auto. Margin is short form, we can also set the margin of the top, right, bottom, left value. For example, we write the following code:

    <style>
        .margin-container {
            background: #333;
            width: 400px;
            height: 200px;
            color: #fff;
        }
        .margin-child {
            margin-top: 10%;
            width: 200px;
            height: 100px;
            background-color: black;
        }
    </style>

    <div class="margin-container">
        <div class="margin-child">
            margin content
        </div>
    </div>
Copy the code

Margin-top: 10%; margin-top: 10%; And this percentage, who is it based on?

Here’s another example:

       <style>
        .padding-container {
            background: #333;
            width: 400px;
            height: 200px;
            color: #fff;
        }
        .padding-child {
            padding-top: 20%;
            width: 200px;
            height: 100px;
            background-color: black;
        }
    </style>
    

    <div class="padding-container">
        <div class="padding-child">
            padding content
        </div>
    </div>
Copy the code

Padding-top: 20%; And based on who calculated the percentage?

If you already know the answer, there’s probably no need to read on. But if you still have any doubts, let’s get to the bottom of it.

Results analysis

Let’s look at the results and think about them in a conventional way. The page has a.margin-container container element and a.margin-child child. Container elements and child elements are set to the appropriate width and height. We all know that block-level elements are arranged vertically in the page, and margin-top is the outer margin of the current set element, so it should be set vertically. Percentages should be calculated according to the height of the element. Let’s leave it at that.

There are two problems here:

  • Margin-top is the percentage set based on the value of its element or the container element?
  • Margin-top is the percentage set based on height or width?

Let’s look at the specific results:

In fact, we can get the answer we want from this picture.

First let’s look at the margin-top value of margin-child set to 10%. In chrome developer Tools, you can see that its margin-top is calculated to be 40px. The width and height of our margin-Child are 200px and 100px, and the width and height of our margin-container are 400px and 200px respectively. Therefore, we can conclude that the margin-top corresponding to the margin-child is 10%, which is 10% of the 400px width of its parent element margin-container. So the answer to the above two questions is:

  • Margin-top sets the percentage based on the value of the container element
  • Margin-top specifies the percentage based on width

Of course, if you look at the padding-top Settings. You’re going to get the same answer. Why is that? Why is it based on width and not height? Why do calculations based on parent elements instead of child elements? In addition, we set the margin-top of the margin-child to 10%. My intuition is that there will be a 10% distance between the margin-child and the margin-container, but from the rendering result, Actually, the distance between margin-Container and body is 10%, which involves the problem of margin merging. If you are not clear, you can refer to relevant questions by yourself.

We learn fromW3C Specification DocumentsIt can be known that:

That’s what the specification says, and that’s how the browser, or the browser’s rendering engine (note: it might not be called that properly), does it. Then why is that a rule? What are the problems with height based calculations?

This article gives some corresponding explanations and summarizes two points:

  • Margin /padding calculations are based on a single value, width, which ensures the consistency of top,right,bottom, and left values
  • Since the height of the parent element is calculated according to the height of the child element, if the margin/padding of the child element is calculated based on the height of the parent element, there will be a circular dependency on height calculation.

Let’s focus on the second point.

Suppose we didn’t set the width and height of the margin-container in our original example

.margin-container {
    background: #333;
    color: #fff;
}
Copy the code
<div class="margin-container">
    <div class="margin-child">
        margin content
    </div>
</div>
Copy the code

The parent element is 714px wide and 100px high. Because there is currently only one child element, the height of the child element is 100px, and the margin-top of the child element is 10% of the width of the parent element, which is 71.4px after calculation. The render shows 71.391px due to errors, and the margin of the child element is merged with the margin of the parent element, so it looks like the parent element is 71.391px away from the top of the body. So the height of the parent element is 100px.

If we calculate the margin percentage by height, the margin-top value of the margin-child should be 100px*10%=10px. It seems that there is no problem, but we know the body width when rendering. Since the width of the margin-Container is not set, we need to calculate its width when rendering the margin-contaner. At this point, we can determine that the width is 714px body width. The height is unknown, and the height needs to be calculated according to the height of the child element, so then the analytic calculation of margin-child is carried out, and it is found that the height of child is 100px, and margin-top is 10% of the height of the parent element, while the height of the parent element is uncertain. So what’s the margin-top of the margin-child?

So some people might say, well, isn’t the height of the parent evaluated by the height of the child? The height of the child element is 100px, so the height of the parent element is 100px, so the margin-top value of the child element is 10px. It would make sense if the browser engine were to parse CSS in the order of resolving child height > calculating parent height > calculating margin.

Let’s look at the following example:

.margin-container {
    background: #333;
    color: #fff;
}
.margin-child {
    margin-top: 10%;
    width: 200px;
    height: 100px;
    background-color: black;
}
Copy the code
<div class="margin-container">
    <div class="margin-child">
        margin content
    </div>
    <div class="margin-child">
        margin content 2
    </div>
</div>
Copy the code

The running results are as follows:

The parent element contains two child elements. The height of the parent element is calculated as the height of the first child element + the height of the second child element + the margin-top of the second child element.

If the browser engine is parsing CSS in the order of child height > parent height > margin, then the browser engine will parse CSS in the order of child height > height > margin. Child height and 200px -> parent height 200px -> child margin-top is 10%=20px. The height of the parent element is calculated as the height of the first child element + the height of the second child element + the margin-top of the second child element. If changes are needed, the height of the parent element will change again, depending on the cycle of travel.

So, do you really understand margin and padding in CSS?

Above is personal shallow view, in fact, there are some not rigorous place, browser for CSS parsing and rendering sequence process, here is the right to throw out the problem, wrong place also hope to point out correction, discuss learning together.