圣杯与双飞翼布局

双飞翼布局是改编自圣杯布局(来源于:In Search of the Holy Grail),两者均是“两侧宽度固定,中间宽度自适应的三栏布局”。

两者不同之处就是在解决中间部分被挡住的问题时,采取的解决办法不一样。

  • 圣杯布局是在父元素上设置了padding-left和padding-right,在给左右两边的内容设置position为relative,通过左移和右移来使得左右两边的内容得以很好的展现。
  • 双飞翼则是在center这个div中再加了一个div来放置内容,在给这个新的div设置margin-left和margin-right 。

圣杯布局

首先定义出整个布局的DOM结构,主体部分是由container包裹的center,left,right三列,其中center定义在最前面。

<div id="header"></div>
<div id="container">
  <div id="center" class="column"></div>
  <div id="left" class="column"></div>
  <div id="right" class="column"></div>
</div>
<div id="footer"></div>

CSS样式上:

Step1: 页面左右预留位置

  1. 在container中使用padding-left, padding-right为左右两边栏各留下150px和200px的宽度。
  2. 分别为左中右三栏设置宽度与浮动,同时对footer设置清除浮动。
#container {
  padding-left: 200px; 
  padding-right: 150px;
}
#container .column {
  float: left;
}
#center {
  width: 100%;
}
#left {
  width: 200px; 
}
#right {
  width: 150px; 
}
#footer {
  clear: both;
}
对container设置padding-left,padding-right。为左右栏预留位置
为左中右设定宽度。中100%,左右按照预留宽度设定。同时对footer清除浮动

Step2: 将左右栏分别移动到即定位置

  1. center的宽度为100%,会占据了第一行的所有空间,因此leftright被“挤”到了第二行。接下来通过负外边距(nagetive margin)left放置到之前预留出的位置上。
  2. 使用Position进行定位,在使用rignt进行左移。
#left {
  width: 200px; 
  margin-left: -100%; // 负外边距

  position: relative;
  right: 200px; // 将left的位置在原有位置基础上左移200px
}
#right {
  width: 150px; 
  margin-right: -150px; 
}
使用外负边距margin-left: -100%;将左栏left移动到和center一行
再使用position:relative进行定位,将左栏左移200px到即定位置
右栏也是使用外负边距margin-right=-150px进行移动。

Step3: 设定页面最小宽度

  1. 为了保证该布局效果正常显示。设定min-width
  2. 最小宽度:左+中+右=200+中+150。
  3. 由于移动left时使用了position: relative,right=200px。因此中间栏还有200px。即最小宽度=200+200+150=550px。

body {
  min-width: 550px;
}

body {
  min-width: 550px;
}
#container {
  padding-left: 200px; 
  padding-right: 150px;
}
#container .column {
  float: left;
}
#center {
  width: 100%;
}
#left {
  width: 200px; 
  margin-left: -100%;
  position: relative;
  right: 200px;
}
#right {
  width: 150px; 
  margin-right: -150px; 
}
#footer {
  clear: both;
}

⚠️注意:为保证中间部分不发生高度坍塌,需要为中间栏设定width:100%

center是浮动元素,由于浮动具有包裹性,在不显式设置宽度的情况下会自动“收缩”到内容的尺寸大小。如果去掉width: 100%,则当中间栏不包含或者包含较少内容时,整个布局会“崩掉”


双飞翼布局

双飞翼布局要点:

  1. 两侧left, right 宽度固定,中间content宽度自适应
  2. 中间content部分在DOM结构上优先,以便先行渲染
  3. 允许三列中的任意一列成为最高列

双飞翼布局实现思路:

  1. 设定header、footer宽度100%,同圣杯布局第一步;
  2. left、right、middle三个区域全左浮动,同圣杯布局第二步;
  3. left、right设置margin-left,让左靠左,右靠右,此时left、right遮挡了middle区域同圣杯第三步;
  4. 将被middle包裹的inside设置margin:0 200px; 给左右留出空间;
  5. 给左侧设置:margin-left: -100%; 给右侧设置:margin-left: -200px; 让左靠左,右靠右,完成双飞翼布局。

圣杯和双飞翼解决中间区域被遮挡:

  1. 圣杯在最开始用容器包裹了:左、中、右,随后通过设置包裹容器container的padding,让中间区域左右留白,也就是说圣杯布局的左、中、右是完全独立的,他们之间是有缝隙的。
  2. 左、中、右是独立的三个区域,都处于一个层级,都由container这个容器(蓝色)承接,左右两侧是靠container的padding留出来的。
  1. 双飞翼采用只处理中间解决遮盖问题,先给中间的包裹器middle加margin,让出左右空间,然后给left、right设置margin为负,把自己推上去。
  2. 可以看出,左、中、右是独立的三个区域,中间区域属于最上面的层级(inner那个div),左右两侧和middle容器一个层级。

使用flex实现圣杯布局:

<!-- DOM结构 -->
<div id="container">
  <div id="center"></div>
  <div id="left"></div>
  <div id="right"></div>
</div>

<style>
  #container {
    display: flex;
  }
  #center {
    flex: 1;
  }
  #left {
    flex: 0 0 200px;
    order: -1;
  }
  #right {
    flex: 0 0 150px;
  }
</style>