在我们正式开始编写圣杯布局和双飞翼布局前首先简要介绍下这种两种布局方式。它们都是为了解决左右两边定宽,中间自适应的三栏布局问题。

再明确下,双飞翼布局主要解决俩问题:1、三列布局,中间宽度自适应,两边定宽; 2、中间栏要在浏览器中优先展示渲染。

而不是简单的实现左右两边定宽,中间自适应就完事了。

# 圣杯布局写法

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .header,
    .footer {
      background-color: red;
    }

    .container {
      overflow: hidden;
      padding: 0 200px 0 200px;
    }

    .container>div {
      float: left;
    }

    .middle {
      width: 100%;
      background-color: yellow;
    }

    .left,
    .right {
      width: 200px;
    }

    .left {
      margin-left: -100%;
      position: relative;
      left: -200px;
      background-color: orange;
    }

    .right {
      margin-left: -200px;
      position: relative;
      left: 200px;
      background-color: green;
    }
  </style>
</head>

<body>
  <div class="header">header</div>
  <div class="container">
    <div class="middle">中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间</div>
    <div class="left">左边内容</div>
    <div class="right">右边内容</div>
  </div>
  <div class="footer">footer</div>
</body>

</html>

效果如下:

但是圣杯布局有个问题 - 最小宽度,当页面缩小的小于最小宽度时布局就会混乱。如图:

那么怎么修复这个问题,既然是当页面缩小到超过最小值时页面就会混乱,那我们只需要给页面设定一个最小值,当达到这个值时页面就不再缩放就行了。问题来了,那这个值我们应该怎么得到呢?

min-width = left-width * 2 + right-width

上面我们展示了圣杯布局的写法,下面来用其他方法实现下两边定宽,中间自适应的的布局,但要注意它们不是圣杯布局。

# 使用flex实现

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .container {
      display: flex;
      height: 600px;
      min-width: 600px;
    }

    .center {
      flex: 1;
      background: orange;
    }

    .left {
      width: 200px;
      background: red;
    }

    .right {
      background: yellow;
      width: 300px;
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="left">左边内容</div>
    <div class="center">中间内容</div>
    <div class="right">右边内容</div>
  </div>
</body>

</html>

效果如下,这种方式中间内容高度可以自适应,展示效果也不错,但是中间内容不是最先展示的。

# 使用float实现

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    .container {
      overflow: hidden;
    }
    .left, .right {
      width: 200px;
    }
    .left {
      float: left;
      background-color: red;
    }
    .middle {
      background-color: orange;
    }
    .right {
      float: right;
      background-color: yellow;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="left">左侧内容</div>
    <div class="right">右侧内容</div>
    <div class="middle">中间内容</div>
  </div>
</body>
</html>

效果如下,上面这种方式,虽然中间内容高度也能自适应,但可以看到当中间高度高于两边后,内容乱了

# 使用绝对定位

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    .header,.footer {
      background-color: green;
    }
    .container {
      min-height: 1.2em;
      position: relative;
    }
    .container div {
      position: absolute;
    }
    .left, .right {
      width: 200px;
    }
    .left {
      background-color: red;
    }
    .middle {
      left: 200px;
      right: 200px;
      background-color: orange;
    }
    .right {
      right: 0;
      background-color: yellow;
    }

  </style>
</head>
<body>
  <div class="header">header</div>
  <div class="container">
    <div class="left">左侧内容</div>
    <div class="middle">中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容</div>
    <div class="right">右侧内容</div>
  </div>
  <div class="header">footer</div>
</body>
</html>

效果如下,高度虽然能自适应,但是会遮挡住底部的footer。

参考:

浅谈面试中常考的两种经典布局——圣杯与双飞翼 (opens new window)