三栏布局(圣杯和双飞翼布局)

最近开始看面试题,并好好将圣杯和双飞翼布局总结归纳发文,关键词:三栏布局圣杯布局双飞翼布局

float浮动三栏布局

CSS样式

less 复制代码
.box {
    width: 100%;
    height: 100%;
    .item {
      height: 100%;
    }
    .left {
      width: 300px;
      background: red;
      float: left;
    }
    .center {
      background: blue;
    }
    .right {
      width: 300px;
      background: green;
      float: right;
    }
  }

DOM书写顺序对样式的影响

左中右顺序

html 复制代码
<template>
  <div class="box" ref="boxRef">
    <div class="left item">左侧</div>
    <div class="center item">中间</div>
    <div class="right item">右侧</div>
  </div>
</template>

实际渲染效果

中左右顺序

html 复制代码
<template>
  <div class="box" ref="boxRef">
    <div class="center item">中间</div>
    <div class="left item">左侧</div>
    <div class="right item">右侧</div>
  </div>
</template>

实际渲染效果

以上,都不是我们需要的三栏布局,三个DIV未在同一列渲染。float浮动脱离文本流的元素不会占据实际位置。中间DIV是会占据渲染位置,并且自适应宽度100%。HTML的渲染是按照DOM的书写顺序逐层渲染的,三列div的书写顺序决定了渲染的实际效果 所以针对以上情况只需要先将float浮动的元素写在最前面,中间center的div最后书写可实现三个div同列渲染的效果。

左右中顺序

html 复制代码
<template>
  <div class="box" ref="boxRef">
    <div class="left item">左侧</div>
    <div class="right item">右侧</div>
    <div class="center item">中间</div>
  </div>
</template>

实际渲染效果

这样在视觉上已经实现了三栏布局,但实际中间的div是占据100%宽度空间,只是两侧浮动遮盖住了。非浮动的块级元素会"环绕"浮动元素,显示在浮动元素未覆盖的区域内。浮动元素会挤占空间,后续普通流中的内容会自动避开浮动元素所占的位置,填充其余空间,而不会直接覆盖浮动元素。

以上float虽然实现了三列布局,但是有很大的问题。在body中添加文字中间的内容会被挤下去,而两侧不会跟随移动。

且如果宽度小于两侧宽度之和右侧元素会被挤下去

所以,以上以float浮动实现的三栏布局不推荐使用。

position定位三栏布局

position实现三栏和float差不多,两侧绝对定位,中间使用margin设置左右宽度实现三栏布局

html 复制代码
<template>
  <div class="box" ref="boxRef">
    <div class="left item">左侧</div>
    <div class="center item">中间</div>
    <div class="right item">右侧</div>
  </div>
</template>
less 复制代码
.box {
    width: 100%;
    height: 100%;
    .item {
      height: 200px;
    }
    .left {
      width: 300px;
      background: red;
      position: absolute;
      left: 0;
      top: 0;
    }
    .center {
      background: blue;
      // maring设置
      margin: 0 300px;
    }
    .right {
      width: 300px;
      background: green;
      position: absolute;
      right: 0;
      top: 0;
    }
  }

圣杯布局

随着页面宽度的变化,三栏布局中的中间盒子自适应,两侧盒子宽度固定不变

js 复制代码
<template>
  <div class="box" ref="boxRef">
    <div class="header">头部</div>
    <div class="content">
      <div class="center item">中间</div>
      <div class="left item">左侧</div>
      <div class="right item">右侧</div>
    </div>
    <div class="footer">底部</div>
  </div>
</template>
less 复制代码
.box {
    width: 100%;
    height: 100%;
    .header,.footer {
      height: 50px;
      width: 100%;
      background: gray;
    }
    .content {
      overflow: hidden;
      padding: 0 300px;
      .item {
        height: 200px;
        float: left;
      }
      .left {
        width: 300px;
        background: red;
        position: relative;
        left: -300px;
        margin-left: -100%;
      }
      .center {
        background: blue;
        width: 100%;
      }
      .right {
        width: 300px;
        background: green;
        position: relative;
        right: -300px;
        margin-left: -300px;
      }
    }
  }

布局修改步骤

  1. 这里的圣杯布局先定义好了header和footer头尾两个布局容器,在原有三栏布局添加了content容器包含左中右三栏容器,并给content添加左右padding增加两侧栏的渲染空间。且left、center、right都添加上float浮动
less 复制代码
.content {
  padding: 0 300px;
  .item {
    height: 200px;
    float: left;
  }
  .left {
    width: 300px;
    background: red;
  }
  .center {
    background: blue;
  }
  .right {
    width: 300px;
    background: green;
  }
}

效果如图:

可以看到上图,因为left、center、right为浮动元素不占据文本流,底部footer自然顶上与头部相接。

  1. content区域的布局已经用下到了footer底部的位置布局。我们希望footer为正常接在content下方渲染。这时候可以给content添加固定高度或者让content容器成为BFC 。给content添加overflow:hidden这里就运用到了面试常考内容之一的BFC,相关概念读者可自行了解。

BFC后的布局样式
3. 因为center中间栏元素需要自动撑满,给center元素添加width:100%。两侧栏会自动掉到下面空间。

4. 这里我们只需要将左右两侧的元素移到中间center两侧为止即可完成相关布局。给left设置left:-100%
可以看到left已经位移到content内部最左侧,这时候还需要继续左移300px。给left盒子添加position: relative和left:-300px

5. 同理,right盒子也设置位移position: relative;right: -300px;margin-left: -300px;

6. 最后的css样式表

less 复制代码
.box {
    width: 100%;
    height: 100%;
    .header,.footer {
      height: 50px;
      width: 100%;
      background: gray;
    }
    .content {
      overflow: hidden;
      padding: 0 300px;
      .item {
        height: 200px;
        float: left;
      }
      .left {
        width: 300px;
        background: red;
        position: relative;
        left: -300px;
        margin-left: -100%;
      }
      .center {
        background: blue;
        width: 100%;
      }
      .right {
        width: 300px;
        background: green;
        position: relative;
        right: -300px;
        margin-left: -300px;
      }
    }
  }

这里解释下为什么left的margin-left设置-100%,right的margin-left设置-300px。参考步骤3 的效果图,margin的负数设置是以父元素包含容器为基准的,left侧栏设置-100%是将left容器位移到content最左侧内容区,然后再使用left负值移动自身的宽度值即可。因为left已经位移到上面,right右侧栏会位移到原left左侧栏的位置,这里只需要将right右侧栏向左移动两个300px即可。所以设置right、margin-left皆为负值的300px。

双飞翼布局

html 复制代码
<template>
  <div class="box" ref="boxRef">
    <div class="header">头部</div>
    <div class="content">
      <div class="center item">
        <div class="center-inner">中间内容</div>
      </div>
      <div class="left item">左侧</div>
      <div class="right item">右侧</div>
    </div>
    <div class="footer">底部</div>
  </div>
</template>

直接贴出html,可以看到跟前面的圣杯布局唯一不同就是在center中间元素添加了一个类名center-inner的子元素。 css样式布局基本和圣杯无变化,但content不用设置padding,center继续设置宽度百分百占满整个content。这样left、right会被挤到下一列。

然后左侧栏设置margin-left:-100%右侧栏设置margin-left:-300px,然后无需设置定位,完成三栏布局的主要样式布局。具体margin设置原理可参考圣杯布局。

可以看到中间center两侧被遮盖住了,这时候添加的center-inner就要发挥用处了。设置该元素两侧padding与左右两栏同宽。最后贴出结果的css

less 复制代码
.box {
    width: 100%;
    height: 100%;
    .header,.footer {
      height: 50px;
      width: 100%;
      background: gray;
    }
    .content {
      overflow: hidden;
      .item {
        height: 200px;
        float: left;
      }
      .left {
        width: 300px;
        background: red;
        margin-left: -100%;
      }
      .center {
        background: blue;
        width: 100%;
        .center-inner {
          padding: 0 300px;
        }
      }
      .right {
        width: 300px;
        background: green;
        margin-left: -300px;
      }
    }
  }

补充:flex三栏布局

flex布局实现三栏布局不做过多描述,直接贴代码

html 复制代码
<template>
  <div class="box" ref="boxRef">
    <div class="header">头部</div>
    <div class="content">
      <div class="left item">左侧</div>
      <div class="center item">中间</div>
      <div class="right item">右侧</div>
    </div>
    <div class="footer">底部</div>
  </div>
</template>
less 复制代码
.box {
    width: 100%;
    height: 100%;
    .header,.footer {
      height: 50px;
      width: 100%;
      background: gray;
    }
    .content {
      display: flex;
      justify-content: space-between;
      .item {
        height: 200px;
      }
      .left {
        width: 300px;
        background: red;
      }
      .center {
        background: blue;
        width: 100%;
      }
      .right {
        width: 300px;
        background: green;
      }
    }
  }

结语

圣杯和双飞翼布局其实相差不大,只是一个用父级设置内边距另一个新增一项子元素设置。两侧栏再利用margin或定位位移到对应位置即可

相关推荐
前端Hardy19 分钟前
HTML&CSS:3D图片切换效果
前端·javascript
spionbo40 分钟前
Vue 表情包输入组件实现代码及完整开发流程解析
前端·javascript·面试
全宝41 分钟前
✏️Canvas实现环形文字
前端·javascript·canvas
lyc23333341 分钟前
鸿蒙Core File Kit:极简文件管理指南📁
前端
我这里是好的呀41 分钟前
全栈开发个人博客12.嵌套评论设计
前端·全栈
我这里是好的呀42 分钟前
全栈开发个人博客13.AI聊天设计
前端·全栈
金金金__43 分钟前
Element-Plus:popconfirm与tooltip一起使用不生效?
前端·vue.js·element
lyc23333344 分钟前
小L带你看鸿蒙应用升级的数据迁移适配📱
前端
用户26812851066691 小时前
react-pdf(pdfjs-dist)如何兼容老浏览器(chrome 49)
前端