Multi-column layouts are very common in a web design, not only can be used to do the layout of external containers, in some parts of the multi-column layout, such as the following are circled multi-column layouts:

Constant width + adaptive

Fixed width | adaptive

Let’s start with the simplest two-column layout, where the left column has a fixed width and the right column is adaptive:

Here’s a look at some ways to solve this problem:

float + margin

We have the following HTML code:

<div class="parent">
  <div class="left">
    <p>left</p>
  </div>
  <div class="right">
    <p>right</p>
    <p>right</p>
  </div>
</div>
Copy the code

This is what it looks like when we don’t style it

We want a two-column layout, so we add a float to left :left; And then it went like this:

We see that the content of right surrounds the left, which is a feature of float. How can we solve this problem? Margin-left: 100px; margin-left: 100px; margin-left: 100px; margin-left: 100px; margin-left: 100px; If you want a bit more space between the left and right columns, make the margin-left a bit bigger.

float + overflow

Float :left; margin :left; margin :left; margin :left; margin :left The right will still surround the left:

This time we will use overflow instead of margin-left:

Margin-right: 20px; margin-right: 20px; . Why overflow: Hidden can not float around the problem, it actually uses the principle of BFC. Let’s talk about BFC:

BFC

A 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.

The following situations can form a BFC:

1. Float element,floatValues other than None; 2. Position (Absolute, fixed); 3. Display: Inline-block, table-cell, table-caption; 4. Overflow values except visible (hidden, auto, scroll);Copy the code

The BFC has the following features:

1. The internal boxes will be placed one after another in the vertical direction. 2. The vertical distance is determined by margin. 3floatElement regions overlap. 5. The BFC is a separate container on the page, and its children do not affect the outside elements.Copy the code

How to understand the above features?

  1. If there are multiple vertical divs, and they all have margins, the vertical margins will merge

    <div class="parent">
      <div class="child"></div>
      <div class="child"></div>
    </div>
    
    .child {
        margin-top: 10px;
        margin-bottom: 20px;
    }
    Copy the code

    In the code above, the spacing between the two children is 20px, not 30px, because vertical margins merge. But if I set another container for the first child above, use overflow:hidden; It becomes a BFC. According to the characteristics of BFC, the child elements of BFC will not affect the outside elements, and the margin will not merge. The spacing between the two children is 30px.

    <div class="parent3">
      <div class="overflow">
        <div class="child3">child4</div>
      </div>
      <div class="child3">child4</div>
    </div>
    
    .child3 {
        margin-top: 10px;
        margin-bottom: 20px;
    }
    
    .overflow {
        overflow: hidden;
    }
    Copy the code
  2. The BFC is a separate container that is not covered by floating elements, nor does the text in it surround the floating elements, and our two-column layout takes advantage of this feature.

  3. When calculating the height of the BFC, the height of the floating element is also calculated.

    .parent {
        overflow: hidden;
    }
    Copy the code

table

We can also use table. If the parent sets display to table, its width is the width of the content, so we need to manually specify a width of 100%. The two children set display to table-cell so that they are actually equivalent to two cells of the table. Since we want to fix the width of the left side, the parent table should use the layout preference, i.e. table-layout: fixed; . We can’t set margins because they’re cells, but we can set padding-right on the left child.

<div class="parent4">
  <div class="left4">
    <p>left4</p>
  </div>
  <div class="right4">
    <p>right4</p>
    <p>right4</p>
  </div>
</div>

.parent4 {
    display: table;
    width: 100%;
    table-layout: fixed;
}

.left4 {
    display: table-cell;
    width: 100px;
    padding-right: 20px
}

.right4 {
    display: table-cell;
}
Copy the code
table-layout

Table-layout has two values:

  • Fixed: The table layout takes precedence. The column width is determined by the table width and column width, regardless of the cell content. In this mode, the browser receives the first row of the table and renders it faster.
  • Auto: This is the default value, indicating that the table content takes precedence, and the column width is set by the widest content in the column cell without a folded row. This algorithm is sometimes slow because it needs to access everything in the table before deciding on the final layout.

flex

Display: flex, set the width of the left child, set the width of the right child to flex:1, and if you want spacing, you can use margin.

.parent5 {
    display: flex;
}

.left5 {
    width: 100px;
    margin-right: 20px;
}

.right5 {
    flex: 1;
}
Copy the code
flex: 1

Flex: 1 is short for flex: 1, 1, 0.

{
    flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
}
Copy the code
  • flex-grow: Sets the scaling of elements. If the total width of the parent element is 500px, the child element is A, B, and Cflex-grow1, 2, 2, their width ratio is 1:2:2, the final width of the three elements is 100px, 200px, 200px;
  • flex-shrink: Sets the shrink ratio of elements. If the parent element has A total width of 500px, it now has five child elements A, B, C, D, and E, and theirflex-shrinkThey’re 1, 1, 1, 2, 2, theirflex-basisAre 120 px. According to the calculation, the total width of the five child elements is 120 * 5 = 600px, which exceeds the parent by 100px, so the child elements need to be shrunk. When it contracts, it goes throughflex-shrinkTo calculate, we found that theyflex-shrinkThe sum is 1 + 1 + 1 + 2 + 2 = 7. So divide the extra 100px into 7 pieces, each about 14px, and follow theflex-shrinkI’m going to shrink. Components A, B, and C are all 1, so they shrink by 14px, and their final width is 120-14 = 106px; D and E have copies of 2, so they should shrink by 14 times2 = 28px and the final width is 120-28 = 92px.
  • Flex-basis: Sets the initial value of the element to which expansion and contraction are based.

Fixed width | set | wide adaptive

Float + overflow: float + overflow: float + overflow: float + overflow: float + overflow: float + overflow

Indefinite width + adaptive

A two-column layout with variable width on the left, depending on the content, and adaptive solutions on the right:

Variable width: float + overflow

The width of the left child is left to its children.

Indefinite width: table

Fixed cannot be set to table-layout because the width of the left side is variable, so we don’t need to set it to auto. The default table width is determined by the content. If the left and right sides of the table are the same length, they may be the same length, with white space, like this:

But what we want is to squeeze the left side into the content area and give all the white space to the right. Just give the left side a very small width like 0.1% or 1px.

Variable width: Flex

Flex again, very similar to the fixed width, just remove the front left width.

.parent5 {
    display: flex;
}

.left5 {
    margin-right: 20px;
}

.right5 {
    flex: 1;
}
Copy the code

Multi – column variable width + adaptive

Float + overflow: float + overflow: float + overflow

width

A uniform width layout is a number of elements, each of which is the same width and may have some space between them. If there is no spacing, this is easy to do, and each element is 25% wide, but if there is spacing and you set it to 25%, the contents of the container will exceed the parent container and fall out. So how do you do that? Taking a closer look at the writings, we can find that they have the following relationship:

C = W * N + G * (N -1); C = W * N + G * n-g; C = W * N + G * n-g; // C = (W + G) * N - G; // C + G = (W + G) * N;Copy the code

C + G = (W + G) * N; The corresponding schematic diagram is:

This time our HTML structure looks like this, with 20px spacing:

<div class="parent6">
  <div class="column"><p>1</p></div>
  <div class="column"><p>2</p></div>
  <div class="column"><p>3</p></div>
  <div class="column"><p>4</p></div>
</div>
Copy the code

Width: float

From the previous formula, we can see that we need to widen the parent level by 20px, which can be achieved by using margin-left: 20px. Padding-left: 20px; box-sizing: border-box; margin-left: 20px; margin-left: 20px; .

.parent6 {
    margin-left: -20px;
}

.column {
    float: left;
    width: 25%;
    padding-left: 20px;
    box-sizing: border-box;
}
Copy the code

One of the drawbacks of using float layouts is that 25% of the layout is dead. This only works for 4 columns, not if you don’t know how many columns.

Such as: wide table

Table layout:fixed the column width is not calculated by content. The default column width is equal. However, we need to pay attention to the implementation, we need to set another container outside the parent, because the use of table will definitely set the parent as table, the width is 100%, can not be widened, the purpose of setting another container is to broaden its use.

Let’s think, can we solve this problem if we don’t put another container outside the parent? We can set the width of the parent to calc(100% + 20px), so the actual content will be 20px to the right, and we can use the relative position to move it 20px to the left:

.parent8 {
    display: table;
    width: calc(100% + 20px);
    table-layout: fixed;
  position: relative;
    left: -20px;
}

.column3 {
    display: table-cell;
    padding-left: 20px;
}
Copy the code

Width: flex

It’s too easy to do this in Flex, just set flex:1 for each child element.

contour

The idea of contour layouts is that when one column of height is raised, another column is also raised.

Such as: table

Table again, the different cells in a row of a table are naturally equal in height.

Table layut:fixed; You do not need to set this parameter. The spacing is done with transparent border-right. Background-clip is a CSS3 property that represents the area to be displayed in the background and has three values:

  • Border-box: The background is cropped to the border box.
  • Padding-box: The background is clipped to the inside margin box.
  • Content-box: The background is cropped to the content box.

Such as: flex

Flex is here again, and it’s very simple, the same as the previous fixed-width + adaptive solution.

This is because flex’s default align-items are stretched to fill the container.

Such as: float

All of the previous layout solutions have floats in them. Can the contour solutions be solved with floats? The answer is yes, but it’s a little bit more difficult. We write a large padding-bottom for both the left and right children on top of the previous constant width + adaptive, so that the height of both children is large, then subtract the height back with an equally large negative margin-bottom and the parent overflow:hidden.

This makes the left and right child elements look the same height, but debugging can see that they are 9999px higher than the parent. This is not the true contour height, the true contour height still need to use the first two schemes.

The ultimate solution: Grid

Grid is an even more powerful layout solution than Flex, so we’ll break it out here and see how we can implement the previous requirements with Grid. We mainly use two properties of the Grid layout:

  • Grid-template-columns: Specifies the columns of the grid layout. Absolute value (pixels), percentage, and auto are supported.
  • Grid-column-gap: column spacing

Fixed width | adaptive

<div class="parent11">
    <div class="left11">
        <p>left11</p>
    </div>
    <div class="right11">
        <p>right11</p>
        <p>right11</p>
    </div>
</div>

.parent11 {
    display: grid;
    grid-template-columns: 100px auto;
    grid-column-gap: 20px;
}
Copy the code

Fixed width | set | wide adaptive

Grid-template-columns = grid-template-columns

grid-template-columns: 100px 100px auto;
Copy the code

width

Grid-template-columns:

grid-template-columns: auto auto auto;
Copy the code

contour

The top three are all equal height, no extra work required.

conclusion

Through the previous layouts, we can see that there are basically three ideas used

  • Float: Float is to float the left side of the element, but this requires the right side to float around the left side. We used margin and BFC to do this. In a contour layout, the floating element scheme is not contour, and we compensate by having a large inner margin followed by a negative margin. This seems to solve the problem, but the true height of the element has changed.
  • table: We use two features of the table in layout, one is passtable-layoutTo control whether layout or content is first if it is set tofixed, a column can be fixed in width regardless of the length of the content. Don’t settable-layout, or set toautoIt’s the same thing because its default value isautoIf we want a column to be blank and shrink to the width of the content, we just give the column a very small width, for example0.1%or1pxWill do. Another feature we used is that cells in the same column of the table are naturally of equal height, and we used this to do the same height layout.
  • flexFlex was built for layout, so it supports a variety of layouts natively, oneflex:1You can let it adapt to the rest of the space, and Flex defaultalign-itemsisstretch“, which makes him naturally isometric on the cross axis. However, CSS3 only introduced this, and some older browsers may not support it.
  • Grid: Grid is more powerful than Flex, and can do two-dimensional layouts directly. We use grid to do one-dimensional multi-column layouts. It also has many properties, you can refer to ruan yifeng’s tutorial. But the Grid is so new that if you want to work with older browsers, you’ll use the previous solution.

Example code: github.com/dennis-jian…

It is not easy to be original, each article has cost the author a lot of time and effort, if this article is helpful to you, please click to support the author, also let more people see this article ~~

See my nuggets round-up for more articles