Original: www.smashingmagazine.com/2019/07/mar…

Translator: Front-end wisdom


Click “like” and then look, wechat search [Big Move the world] pay attention to this person without dACHang background, but with a positive attitude upward. In this paper, making github.com/qq449245884… Has been included, the article has been categorized, also organized a lot of my documentation, and tutorial materials.

Everyone said there was no project on your resume, so I found one and gave it away【 Construction tutorial 】.

When we learn CSS, the first thing most of us learn is the details of the various parts of the box in CSS, which are called CSS boxes, models. One of the elements in the box model is the margin, the transparent area around the box that pushes other elements away from the box content.

The margin-top, margin-right, margin-bottom, and margin-left properties are described in CSS1, as well as the shorthand margin for setting all four properties at once.

Margins seem like a fairly simple thing to do, but in this article, we’ll look at some of the confusing and interesting things about using margins. In particular, how margins interact with each other and how margins overlap.

To read more quality articles pleaseJabber at the GitHub blog, a hundred quality articles a year waiting for you!

CSS box model

The CSS box model refers to how the various parts of a box — content, padding, border, and Margin — were previously laid out and interacted, as shown below:

The box’s four margin attributes and maring abbreviations are defined in CSS1.

The CSS2.1 specification has an illustration of a box model and defines terms used to describe various boxes, including content box, padding box, border box, and margin box.

There is now a draft of the Level 3 Box Model Specification. This specification refers to CSS2 as the definition of box models and margins, so we will use the CSS2 definition for most of this article.

Margin overlap

The CSS1 specification defines margins, as well as vertical margin overlap. Margin overlap makes sense if you consider that CSS was used as a document format language in its early days. Margin overlap means that when a headline with a bottom margin is followed by a paragraph with a top margin, there is no big white space between them.

When two margins overlap, they are combined and the larger space between the two elements is taken. The smaller margin is inside the larger one.

Margins overlap in the following cases:

  • An adjacent sibling
  • Completely empty box
  • Parent element and first or last child element

Take a look at each of these scenarios in turn.

An adjacent sibling

The initial description of margin overlap was to demonstrate how margins between adjacent siblings overlap. In addition to the cases mentioned below, if two elements are displayed in sequence in normal flow, the bottom margin of the first element will overlap with the top margin of the following element.

In the following example, there are three div elements. The top and bottom margins of the first div are both 50px. The second div has a margin of 20px at the top and bottom. The top and bottom margins of the third div are both 3em. The margin between the first two elements is 50px, because the smaller top margin is combined with the larger bottom margin. The margin between the second element and the third element is 3em, because 3em is larger than the bottom margin of the second element by 20px.

html

<div class="wrapper">

<div class="box example1">
  margin-top: 50px; margin-bottom: 50px;
</div>

<div class="box example2">
  margin-top: 20px; margin-bottom: 20px;
</div>

<div class="box example3">
  margin-top: 3em; margin-bottom: 3em;
</div>
  
</div>
Copy the code

css

.wrapper { border: 5px dotted black; } .example1 { margin: 50px 0 50px 0; } .example2 { margin: 20px 0 20px 0; } .example3 { margin: 3em 0 3em 0; } body {font: 1.4em/1.3 "Gill Sans", "Gill Sans MT", Calibri, sans-serif; margin: 2em 3em; }. Box {background-color: RGB (50, 50, 50); background-color: RGB (50, 50, 50); color: white; padding: 20px; border-radius: .5em; }Copy the code

Operation effect:

Completely empty box

If a box is empty, its top and bottom margins may overlap. In the example below, the element with class empty has a margin of 50px at the top and bottom, but the margin between the first and third items is 50px instead of 100px. This is caused by the overlap of the two margins. Putting content into an empty box prevents margin merging.

html

div class="wrapper">

<div class="box">
  A box
</div>

<div class="box empty"></div>

<div class="box">
  Another box
</div>
  
</div>
Copy the code

css

.wrapper { border: 5px dotted black; } body {font: 1.4em/1.3 "Gill Sans", "Gill Sans MT", Calibri, sans-serif; margin: 2em 3em; }. Box {background-color: RGB (50, 50, 50); background-color: RGB (50, 50, 50); color: white; border-radius: .5em; } .empty { margin: 50px 0 50px 0; }Copy the code

Operation effect:

Parent element and first or last child element

Margin overlap can catch you off guard because it’s sometimes not intuitive. In the following example, we have a div with class wrapper and give the div a red outline so we can see where it is.

The three children of this div all have a margin of 50px. But you’ll notice that the actual effect is that the first and last items are flush with the parent element’s margin, as if there is no 50px margin between the child element and the parent element.

html

<div class="wrapper">

<div class="box">
  Item 1
</div>

<div class="box">
  Item 2
</div>

<div class="box">
  Item 3
</div>
  
</div>
Copy the code

css

.wrapper { outline: 1px solid red; } .box { margin: 50px; } body {font: 1.4em/1.3 "Gill Sans", "Gill Sans MT", Calibri, sans-serif; margin: 2em 3em; }. Box {background-color: RGB (50, 50, 50); background-color: RGB (50, 50, 50); color: white; padding: 20px; border-radius: .5em; }Copy the code

Operation effect:

This is because margins on the child node overlap with margins on either side of the parent node and end up outside the parent node. You can see this if you use DevTools to check the first child element, and the yellow area shown is the margin.

Only the block element margin overlaps

In CSS2, only vertical margin overlap is specified, that is, the top and bottom margin of an element. Therefore, the left and right margins above do not overlap.

Note that margins overlap only in the direction of the block, such as between paragraphs.

Prevent margin overlap

If an element is absolutely positioned, or floating, its margins never overlap. However, assuming you encounter some of the situations in the example above, how do you prevent margin overlap?

For example, if a completely empty box has a border or padding, its upper and lower margins will not overlap. In the example below, add 1px padding to the empty box. The empty box now has a 50px margin above and below it.

html

<div class="wrapper">

<div class="box">
  A box
</div>

<div class="box empty"></div>

<div class="box">
  Another box
</div>
  
</div>
Copy the code

css

.wrapper { border: 5px dotted black; } body {font: 1.4em/1.3 "Gill Sans", "Gill Sans MT", Calibri, sans-serif; margin: 2em 3em; }. Box {background-color: RGB (50, 50, 50); background-color: RGB (50, 50, 50); color: white; border-radius: .5em; } .empty { margin: 50px 0 50px 0; padding: 1px; }Copy the code

Operation effect:

The logic behind this is that if the box is completely empty, with no border or padding, it is essentially invisible. It could be a paragraph element in the CMS marked as empty. Margin overlap makes sense if your CMS is adding redundant paragraph elements and you don’t want them to create large margins between other paragraphs.

If the parent element overlaps with the first or last child element margin, if we add a border to the parent, the margin on the child remains inside.

. .wrapper { border: 5px dotted black; }...Copy the code

Again, there is some logic to this behavior. If elements are wrapped for semantic purposes, but they are not displayed on the screen, you may not want them to introduce large margins in their display. This made a lot of sense when the Web was mostly text. When we use elements for layout design, their overlapping behavior doesn’t make much sense.

Creating a Formatting Context (BFC)

Block Formatting Context (BFC) is a CSS rendering mode for the layout of a box model in a Web page. It refers to an independent rendering area or an isolated independent container.

BFC prevents margin overlap. If we look at the example of the parent element and the first or last child element, we can create a new BFC by adding display: flow-root to the Wrapper element to prevent margin merging

. .wrapper { outline: 1px solid red; display: flow-root; }...Copy the code

Display: flow-root is a new property in CSS3 that creates a BFC with no side effects. Setting the overflow property to auto has the same effect, as this also creates a new BFC, although it may also create some scrollbars that are not needed in some scenarios.

Flex and Grid containers

The Flex and Grid containers establish flex and Grid formatting contexts for their children, so they also prevent margin overlap.

Using the above example, change the wrapper layout to Flex:

. .wrapper { outline: 1px solid red; display: flex; flex-direction: column; }...Copy the code

Website Margin strategy

Since margins overlap, it’s best to find a consistent way to handle your site’s margins. The simplest approach is to define margins only at the top or bottom of the element. In this way, margin overlap is rarely encountered, because edges with margins are always adjacent to edges without margins.

This solution does not solve the problem you might encounter because the margin of the child element overlaps with the parent element. This particular problem tends to be less common, but knowing why it happens can help you come up with a solution.

An ideal solution to this is to set the element to display: flow-root, but some browsers don’t support it. You can use overflow to create a BFC, or set the parent element to a Flex container, and of course you can set the padding.

The percentage margin

When you use percentages in CSS, it must be a percentage of an element. Margin (or padding) set with a percentage is always the percentage of the parent element’s inline size (width in horizontal write mode). This means that the padding around the element is the same when using percentages.

In the following example, we have a 200px wide d when with a div class named Box and a margin of 10%, which is 20px (200*10%).

html

 <div class="wrapper">
  <div class="box">
    I have a margin of 10%.
  </div>
</div>
Copy the code

css

* { box-sizing: border-box; } .wrapper { border: 5px dotted black; width: 200px; }. Box {background-color: RGB (50, 50, 50); background-color: RGB (50, 50, 50); color: white; padding: 20px; border-radius: .5em; margin: 10%; } body {font: 1.4em/1.3 "Gill Sans", "Gill Sans MT", Calibri, sans-serif; margin: 2em 3em; }Copy the code

We’ve been talking about vertical margins throughout this article, however, modern CSS tends to think of things in terms of flow rather than in physical terms. Therefore, when we talk about vertical margins, we are really talking about margins for block dimensions. If we were in horizontal writing mode, these margins would be top and bottom, but in vertical writing mode, these margins would be right and left.

Once logical, flow-dependent directions are used, it is easier to talk about the beginning and end of a block rather than the top and bottom of a block. To simplify this process, CSS introduces logical property and value specifications. This maps the relevant properties of the flow to physical properties.

  • margin-top = margin-block-start
  • margin-right = margin-inline-end
  • margin-bottom = margin-block-end
  • margin-left = margin-inline-start

There are also two new shortcuts for setting two blocks or two inner blocks at the same time.

  • margin-block
  • margin-inline

In the following example, using these stream-related keywords and then changing the writing mode of the box, you can see how the margin follows the direction of the text:

html

<div class="wrapper horizontal-tb">
  <div class="box">
    A box with a horizontal-tb writing mode.
  </div>
</div>

<div class="wrapper vertical-rl">
  <div class="box">
    A box with a vertical-rl writing mode.
  </div>
</div>
Copy the code

css

* { box-sizing: border-box; } .wrapper { border: 5px dotted black; inline-size: 200px; } .horizontal-tb { writing-mode: horizontal-tb; margin-bottom: 1em; } .vertical-rl { writing-mode: vertical-rl; }. Box {background-color: RGB (50, 50, 50); background-color: RGB (50, 50, 50); color: white; padding: 20px; border-radius: .5em; margin-block-start: 30px; margin-block-end: 10px; margin-inline-start: 2em; margin-inline-end: 5%; } body {font: 1.4em/1.3 "Gill Sans", "Gill Sans MT", Calibri, sans-serif; margin: 2em 3em; }Copy the code

To learn more, read more about logical properties and values on MDN.

The bugs that may exist after code deployment cannot be known in real time. In order to solve these bugs, I spent a lot of time on log debugging. Incidentally, I recommend a good BUG monitoring tool for youFundebug.

communication

This article is updated every week, you can search wechat “big move the world” for the first time to read and urge more (one or two earlier than the blog hey), this article GitHub github.com/qq449245884… Have included, sorted out a lot of my documents, welcome Star and perfect, everyone interview can refer to the examination site review, in addition to pay attention to the public account, background reply welfare, you can see welfare, you know.