# 三栏式布局

相关代码地址：<https://github.com/Xia-Ao/baidu-course/tree/master/xiaowei/layout> 要求：左右两边固定宽度，中间居中，宽度自适应！\
下面探讨一下有关三栏式布局的所有方法\
给定一个[html模板](https://github.com/Xia-Ao/Notes/tree/ab1e92e4c0cfe81285aefb761fb815864415503f/template.html), 要求在这个模板上尽可能用多种方法实现三栏式布局

```markup
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>flex</title>
    <style type="text/css">
        body, html {
            margin: 0;
            padding: 0;
        }

        .left, .right, .center {
            height: 200px;
        }
        .left{
            background: yellow;
        }
        .right{
            background: green;
        }
        .center{
            background: red;
        }
    </style>
</head>
<body>
<div class="layout">
    <div class="left"></div>
    <div class="center"></div>
    <div class="right"></div>
</div>
</body>
</html>
```

## 1、flex布局

这是CSS3主推的布局模式，目前也是用的最多的，简单来说就是顺着主轴依次放3列，内容在最前，通过order控制显示顺序，通过flex-grow让中间占据全部剩余空间，通过flex-basis设置左、右div的宽度。\
个人也是优先推荐使用flex实现三栏式布局。\
给父元素的display属性设置为flex布局，然后左右元素设定宽度，中间自适应原始宽度设置为100%，如果顺序不对，使用使用order属性重新排序。

```css
.layout{
    display: flex;
}
.left{
    flex:0 1 120px;
    background: yellow;
}
.right{
    flex:0 1 120px;
    background: green;
}
.center{
    flex: 0 1 100%;
    background: red;
}
```

## 2、绝对定位

左右元素设置position设置为绝对定位，便脱离的文档流，然后中间元素的`margin-left`和`margin-right`设置为左右元素的宽度。\
注意：right如果在文档流最后要设置top=0，一般选择将right文档流放在center元素之前。

```css
.left{
    position: absolute;
    left:0;
    width: 120px;
    background: yellow;
}
.right{
    position: absolute;
    right:0;
    top:0;
    width: 120px;
    background: green;
}
.center{
    margin-left: 120px;
    margin-right: 120px;
    /*width:100%;*/
    background: red;
}
```

## 3、float浮动脱离文档流

其实和绝对定位的原理有点相似，都是是左右元素脱离文档流，不占据中间元素的文档流。\
注意：将中间的内容放在HTML结构的最后，否则右侧会沉在中间内容的下侧

```markup
<div class="layout">
    <div class="left"></div>
    <div class="right"></div>
    <div class="center"></div>
</div>

.left {
    float: left;
    width: 120px;
    background: yellow;
}

.right {
    float: right;
    width: 120px;
    background: green;
}

.center {
    margin: 0 120px 0 120px;
    background: red;
}
```

## 4、BFC+float不会与浮动区域重叠

BFC布局有一个很重要的特点，BFC区域不会与float box重叠，BFC区域会保留float部分，利用这个特点，实现三栏式布局

```markup
.left {
    float: left;
    width: 120px;
    background: yellow;
    overflow: hidden;
}

.right {
    float: right;
    width: 120px;
    background: green;
}

.center {
    background: red;
    overflow: hidden;
}
```

## 5、圣杯布局

原理：将中间文档流放在前面，宽度设置为100%，然后将中间元素、左元素、右元素全部设置为`float：left`，然后给父元素左右margin设置为左右元素宽度，这样，结果就是中间元素占据一整行，左右元素另起一行向左浮动。

```markup
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>圣杯布局</title>
    <style type="text/css">
        body, html {
            margin: 0;
            padding: 0;
        }

        .left, .right, .center {
            height: 200px;
        }

        .layout {
            margin-left: 120px;
            margin-right: 120px;
        }

        .left {
            float: left;
            width: 120px;
            background: yellow;
        }

        .right {
            float: left;
            width: 120px;
            background: green;
        }

        .center {
            float: left;
            width: 100%;
            background: red;
        }
    </style>
</head>
<body>
<div class="layout">
    <div class="center">center</div>
    <div class="left">left</div>
    <div class="right">right</div>
</div>
</body>
</html>
```

效果如下：

![](https://4236962461-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LI4XIh9ljNl7vLDogAQ%2F-LI4XSJWR6h8WVO802xk%2F-LI4Xe4_ORQKxKQQMg04%2Flayout1.png?generation=1532322558481503\&alt=media)

接下来就是想办法把左右元素定位到相对应的位置，这里使用margin负值将元素左移，左边元素左移整个宽度，然后再相对定位到最左边。`margin-left:-100%`将左边元素移动到上面，再使用相对定位，将左边元素移动到父元素margin留出的位置。

```markup
.left {
    float: left;
    width: 120px;
    margin-left: -100%;
    position: relative;
    left: -120px;
    background: yellow;
}
```

效果如下：

![](https://4236962461-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LI4XIh9ljNl7vLDogAQ%2F-LI4XSJWR6h8WVO802xk%2F-LI4Xe4cDi6kmq3l8cbq%2Flayout2.png?generation=1532322558538322\&alt=media)

然后再将右边元素向左移动120px，margin-left:-120px，再相对定位到最右边。

```markup
.right {
    float: left;
    width: 120px;
    margin-left: -120px;
    position: relative;
    right: -120px;
    background: green;
}
```

最终效果如下：

![](https://4236962461-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LI4XIh9ljNl7vLDogAQ%2F-LI4XSJWR6h8WVO802xk%2F-LI4Xe4ei3t4DfdSip6F%2Flayout3.png?generation=1532322558649709\&alt=media)

## 6、双飞翼布局

出自淘宝前端UED团队，它将内容比作鸟的身体，左右比作双翼，所以叫作双飞翼。 它与圣杯布局很像，也是全部往左浮动，但是在中间div里再嵌套一个div，设置子div的margin为左右div预留位置，左右div只设置margin负值即可实现。与圣杯布局相比，少了position:relative，多了一个div。

```markup
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>圣杯布局</title>
    <style type="text/css">
        body, html {
            margin: 0;
            padding: 0;
        }

        .left, .right, .content {
            height: 200px;
        }
        .left{
            float: left;
            width: 120px;
            margin-left:-100%;
            background: yellow;
        }
        .right{
            float: left;
            width: 120px;
            margin-left:-120px;
            background: green;
        }
        .center{
            float: left;
            width:100%;

        }
        .content{
            margin:0 120px;
            background: red;
        }
    </style>
</head>
<body>
<div class="layout">
    <div class="center">
        <div class="content">content</div>
    </div>
    <div class="left">left</div>
    <div class="right">right</div>
</div>
</body>
</html>
```

## 7、table布局

```markup
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>flex</title>
    <style type="text/css">
        body, html {
            margin: 0;
            padding: 0;
        }

        .left, .right, .center {
            height: 200px;
            display: table-cell;
        }
        .layout{
            display: table;
            width: 100%;
        }
        .left{
            width:120px;
            background: yellow;
        }
        .right{
            width: 120px;
            background: green;
        }
        .center{
            background: red;
        }
    </style>
</head>
<body>
<div class="layout">
    <div class="left"></div>
    <div class="center"></div>
    <div class="right"></div>
</div>
</body>
</html>
```

缺点：无法设置格间距，并且左右元素display属性不能为none。

后面还有一种说法使用inline-block布局，尝试过之后发现其实并不好用。

## 参考

* [详解 CSS 七种三栏布局技巧](https://zhuanlan.zhihu.com/p/25070186)
* [css 三栏布局 圣杯布局 双飞翼 flex](http://blog.csdn.net/wangjun5159/article/details/78764774)
* [浮动元素margin负值的应用](http://www.cnblogs.com/fbzs/p/6373315.html)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xia-ao.gitbook.io/notes/yu-yan/css/san-lan-shi-bu-ju.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
