The padding in the box size is responsible for the inside margin. In general (except for the weird phenomenon in the previous chapter), it doesn’t cause too much trouble for the user. Therefore, the author calls it a mild padding, while the margin is more radical. It also comes with some special attributes (such as overlay). This paper will deeply explore the use of margin negative margin and the generation and calculation method of overlay through examples

1. The correct way to open negative margins

When talking about margin, we usually think of a transparent margin, which is used to define the boundary between elements. However, margin can not only define the boundary, but also change the “visual size” of elements. Note that I did not use the internal size here, because margin and padding are almost complementary in changing the visual size of elements. Padding changes the visual size of an element when width is set or the element remains “wrapped”, while margin changes the visual size only when the element is “fully utilized”. Of course, these two are not completely complementary, here as a thinking, please experience.

Width elements and elements that remain “wrapped” do not affect the visual size of a margin. Width is easy to understand.

Absolute, fixed, float, inline-box(inline-block, table-cell, table-caption, flex, inline-flex)

So when we encounter the above elements, we don’t need to try to change their viewable area with margin, it doesn’t work. Since my favorite inline-block element is also in there, I rarely use margin negative to manage the visual area of elements. Here’s a simple demonstration of how a negative margin affects the visual area of an element:

<div class="father">
    <div class="son"></div>
</div>
<style>
.father{
    width: 300px;
    height: 200px;
    background: #F56C6C;
}
.son{
    margin: 0 -20px;
    height: 100px;
    background: #E6A23C;
}
</style>
Copy the code

Since the Markdown editor supports markup language, we can preview the final look directly as follows (hint: you can check the following elements directly in your browser to see the CSS style)

There are two points to note here. First, son is the display element whose default is block, which conforms to the rule of making full use of horizontal space. Second, son does not declare width itself, so width under the effect of negative margin final width = father.width + 20*2, as shown in the figure above.

In addition to changing the viewable area of “fully available space,” negative margins can also take advantage of their ability to change size to achieve some special layout effects. Examples given by the author are as follows:

<div class="box box-right-same">
    <div class="full">
        <p>In the DOM document flow, the image is fixed width on the right, and the visual rendering is also on the right, which is incidentally consistent.</p>
    </div>
    <img src="1.jpg" class="img">
</div>
<style>
/* Float right, image DOM behind, consistent with visual representation */
.box-right-same > .full {
    width: 100%;
    float: left;
}
.box-right-same > .full > p {
    margin-right: 140px;
}
.box-right-same > img {
    float: left;
    margin-left: -128px;
}
</style>
Copy the code

The results are shown below:

In this case, since full is 100% wide and both it and the img element are floating elements, the img element should flow below the full element before margin is set. With negative margins, the img element’s width is increased by 128px, which is exactly the width of the image. The img element itself becomes “0 width “, so the 0 width element floats because it “doesn’t need” to occupy the width, its width is provided by the negative margin. (I reserve my opinion on this part of the test. If you have different views, please leave a comment below.)

2. Deeply explore the three conditions of margin merger

The margin-top and margin-bottom margins of block-level elements sometimes overlap, a phenomenon called margin merging. By definition, two pieces of information can be confirmed.

(1) Block-level elements

(2) Vertical direction. Without regard to writing-mode, the document flow defaults to horizontal, so vertical here refers to the direction perpendicular to the document flow, not simply up, down, left, and right.

Margin merging generally has three scenarios

(1) Margin merges adjacent sibling elements.

(2) Parent and first/last child element. (The author may have some problems with this expression, which needs to be combined with the third point)

(3) Margin merging of empty block-level elements.

Below I will list some scenes to explore which margins of each scene are overlapped.

<p>A paragraph</p>
<p>A paragraph</p>
<p>A paragraph</p>
<p>A paragraph</p>
<style>
p{
    margin: 1em 0;
}
</style>
Copy the code

The results are shown below:

In this example, it is clear that the margin of the p tag is 1em, but the distance between each two lines is not 1+1=2, but 1 and 1= 1. Let’s look at the second scenario.

<div class="father">
    <div class="son"></div>
</div>
<style>
body{
    margin: 0;
}
.father{
    background: green;
    height: 400px;
}
.son{
    margin-top: 200px;
    height: 200px;
    background: red;
}
</style>
Copy the code

The results are shown below:

In this case, the parent element has a height of 400, the child element has a height of 200, and the upper margin is 200. Presumably, the child element should be “positioned” at the bottom of the parent container, but due to the margin overlapping between the parent and the first/last child element (we’ll prove whether this theory is entirely correct in the following example), The child element’s margin-top is “borrowed” to the parent element, and then its own margin-top seems to become 0. In actual development, the margin combination of the parent element and the child element will also bring us a lot of trouble. Then, how to solve this trouble? The author offers several options (satisfying any one of them), and HERE I have some of my own ideas.

  • (1) The parent element is set to block format context element (overflow:hidden)

  • Border-top /bottom (>0); border-top/bottom (>0); border-top/bottom (>0);

  • Padding-top /bottom (>0);

  • (4) Add a (non-empty) inline element to separate the parent element from the first child element (for margin-top)

  • (5) Add a (non-empty) inline element to separate the parent element from the last child element (for margin-bottom)

  • (6) Set height, min-height or max-height for the parent element (note that this rule only applies to margin-bottom)

In my tests, the CSS world doesn’t seem to like this. I say border/padding is ok, but I say 0, “wow” doesn’t work, so I add a >0 constraint, but since this rule breaks the container size, I don’t recommend either solution.

At the time of actual validation, article 4 / article 5 in the Google browser will also be due to “0” values are not effective, so I crossed out it, because the solution is so stupid, you must write something in inline element to solve the problem of margin veiw, this much more severe than damage container size, directly affect the text display. So the best solution is the first one, the parent element is set to block formatting context elements, although I don’t know what that means.

To move on to today’s highlight, I think the author wrote a problem point, let’s start by adding an empty block level tag on the basis of the parent and child overlapping code.

<div class="father">
    <! -- I am an empty block level element -->
    <div></div>
    <div class="son"></div>
</div>
<style>
body{
    margin: 0;
}
.father{
    background: green;
    height: 400px;
}
.son{
    margin-top: 200px;
    height: 200px;
    background: red;
}
</style>
Copy the code

In fact, there are two knowledge points involved here. First, the margin of the empty block-level tag is overlapped. Since it has no width and height and no margin value, it only overlapped with the adjacent son element. Margin-bottom :0 for the empty div and margin-top:200 for the son element; margin-bottom: 200 for the empty div; margin-bottom: 200 for the son element 200 merges with its own margin-top:0, so that its own margin-top is also infected and finally overlapped into an empty block-level element with a vertical margin of 200. At this time, the parent element senses that its first child element has margin-top and performs a wave of margin-top overlapped with it. So the final performance is the same as in the second example.

At this point, I was ok with the test, but then I realized that the inline empty tag doesn’t have any effect on the second example, so what does the superimposition of the parent and the first/last child mean? Thinks that between the parent and the first child to add inline elements seem to have any other meaning, I want to express personal guess the writer is an inline element is destroyed in the overlying three rules, because inline element does not happen margin veiw, therefore the segmentation can be used (even if the inline element is empty, Of course, being empty in real tests has no effect). Based on my test results, I made a bold assumption that margin overlaid will simply ignore all empty tags (of course, empty tags can’t have any weird styles). In this way, the inline empty label problem is solved. Of course, this hypothesis has yet to be tested, so try your luck on the forums provided by the authors.

3. Calculation rules for margin merging

As for the calculation rules of margin merging, I personally tend to completely follow the author’s three penetrating summaries:

  • “Positive takes maximum value”
  • “Plus and minus”
  • “Negative negative most negative”

I’m just going to show you what happens when you add pluses and minuses, even though it’s not really a soft thing to use, so let’s see what happens next, right

.a{margin-bottom:50px}
.b{margin-top:-20px}
<div class="a"></div>
<div class="b"></div>
Copy the code

The spacing between a and B =-20+50 = 30px

4. In-depth understanding of margin: Auto

Always named after in-depth, is actually a 🐶 test, according to the result of the performance of the browser, to guess the principle, in understanding the margin: auto before, first look at the example below.

<div class="father">
    <div class="son"></div>
</div>
<style>
body{
    margin: 0;
}
.father{
    height: 400px;
    background: yellow;
}
.son{
    width: 200px;
    margin-right: 100px;
    margin-left: auto;
    height: 200px;
    background: red;
}
</style>
Copy the code

The results are shown below:

The following conclusions can be drawn from the results:

(1) Margin :auto is useful. If margin-left:auto is removed, margin-right becomes invalid

(2) Margin: The auto attribute manages the remaining space of the container

What is the remaining space of the container? The most common scenario is when you add a width to the body

So the question arises again, why is it not vertically centered in the vertical direction? The reason is that there is a precondition for triggering margin:auto calculation, that is, when width or height is auto, the element has the automatic filling attribute of the corresponding direction. In this example, when the width of son is auto, the width of son is 100%, so the rest of the space is 100% width. When the height of son is auto, the height of son is 0, so you can’t see it. Height: auto also does not meet the auto fill feature.

Using margin: Auto to manage the remaining space, we can not only achieve horizontal centering of elements, but also achieve “right float” of elements. Only the following Settings are required.

<div class="father">
    <div class="son"></div>
</div>
<style>
body{
    margin: 0;
}
.father{
    height: 400px;
    background: yellow;
}
.son{
    width: 200px;
    margin-left: auto;
    height: 200px;
    background: red;
}
</style>
Copy the code

Here we manage the remaining space with margin-left:auto, and the elements are automatically right-aligned.

In addition to horizontal center and right aligned, Margin: Auto also supports horizontal and vertical center. As mentioned earlier, to achieve vertical centering, all you need is for the element to have auto-fill in the vertical direction, height: Auto. So when does height: Auto have an autofill property? There is one case where you can absolutely position an element and when you set the top and bottom attributes, the element will automatically fill the parent container vertically. As shown below.

<div class="father">
    <div class="son"></div>
</div>
<style>
body{
    margin: 0;
}
.father{
    height: 400px;
    background: yellow;
    position: relative;
}
.son{
    position: absolute;
    width: 200px;
    height: 200px;
    background: red;
    margin: auto;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
}
</style>
Copy the code

Since the right, left, top, and bottom values are set, the child elements are automatically filled in both vertical and horizontal directions, and the remaining space is managed by margin.

I’ll leave you there for the margin section.

Never forget why you started, and your mission can be accomplished.

You can also scan the QR code to enter the blogger’s fan group (708637831). Of course, you can also scan the QR code to reward and directly keep a handsome blogger.