圣杯布局(holy grail)总结

96
一拾五
2018.01.14 13:08 字数 535

什么是圣杯布局?

根据 wikipedia词条,圣杯指多列等高的网页布局。因为目前的实现方法都存在局限,而又很难找到一个最优解,圣杯因此而得名。

holy-grail.png

在[Matthew Levine 的文章](In Search of the Holy Grail http://alistapart.com/article/holygrail) 中提到了圣杯的五个要求:

  • 中间列宽度自适应(fluid),两边列宽度固定
  • 在源文档(source)中,中间列处于侧边两列之前
  • 任意一列都可以作为最高列
  • 除了必要的元素之外,只多出一个div标签
  • 用简洁的CSS实现,尽量减少hack

Padding Solution

这个方法来自[Matthew Levine 的文章](In Search of the Holy Grail http://alistapart.com/article/holygrail)。

实现思路:在三列之外包上一个div,通过padding留出左右列的空间,再通过 relative positon 把左右列移动到合适位置。

  1. 首先通过 float: left 把三个div排到同一行,并分别设置三列的宽度
  2. 在三列之外包上一个div,设置其左右padding分别为左右列的宽度
  3. 对左列设置 margin-left: -100% 从而移动到最左侧。通过 position: relative, right: [width_of_left_col] 把左列移动到padding留出的左侧空间。
  4. 使用 position: relative, right: -[width_of_right_col] 把右列移动到padding留出的右侧空间。
  5. 对 footer 设置 clear: both, 防止和三列重叠。
  6. 中间列的最小宽度不能低于左列宽度。
// HTML

<div class="body">
  <div class="header">header</div>
  <div class="container">
    <div id="center" class="column">
      main            
    </div>
    <div id="left" class="column">
      nav
    </div>
    <div id="right" class="column">
      ads
    </div>
  </div>
  <div class="footer">footer</div>
</div>
// CSS

.body {
  min-width: 600px;
}

.footer {
  clear: both;
}

.container {
  padding: 0 200px;
}

.column {
  position: relative;
  float: left;
}

#center {
  width: 100%;
}

#left {
  width: 200px;
  margin-left: -100%;
  right: 200px;
}

#right {
  width: 200px;
  margin-right: -200px;
}

Margin Solution

  1. 在center column外面套一层div,宽度为100%。
  2. 两边列和中间div都为float:left,使三列同行显示。
  3. 对左列margin-left:-100%,使其定位于最左的宽度。
  4. 中间列两边设置margin分别为左右列的宽度。
  5. 右边列设置margin-left为负自己的宽度,使其缩进wrapper里面
// HTML

<div class="header">header</div>

<div class="center-wrapper">
  <div id="center">
    main
  </div>
</div>
<div id="left">nav</div>
<div id="right">ads</div>

<div class="footer">footer</div>


// CSS
.footer {
  clear: both;
}

.center-wrapper {
  float: left;
  width: 100%;
}

#center {
  margin: 0 200px;
}

#left {
  float: left;
  width: 200px;
  margin-left: -100%;
}

#right {
  float: left;
  width: 200px;
  margin-left: -200px;
}

Flexbox Solution

最简单的实现方法。

<div class="header">header</div>

<div class="container">
  <div id="center">
    main
  </div>
  <div id="left">nav</div>
  <div id="right">ads</div>
</div>

<div class="footer">footer</div>
.container {
  display: flex;
}

#left {
  width: 200px;
  order: -1;
}

#right {
  width: 200px;
}

#center {
  flex: 1;
}

Follow-up

当窗口很狭窄的时候,把左边列移动到中间列之上,右边列移动到中间列之下。

holy-grail-stack.png
// CSS
@media(max-width:600px){
  .container{
    flex-direction: column;
  }
}
技术随笔
Web note ad 1