别再让三栏布局把你“拦”住了!

323 阅读3分钟

三栏布局一般指的是页面中一共有三栏,左右两栏宽度固定,中间自适应的布局,三栏布局的具体实现

浮动

利用浮动,左右两栏设置固定大小,并设置对应方向的浮动。中间一栏设置左右两个方向的margin值,注意这种方式,中间一栏必须放到最后

浮动元素的布局有个特点:其摆放的位置会避开常规流元素(书写在浮动元素前面的常规流元素),但后面的常规流元素依然会与其进行重叠

所以如果我们要利用浮动的方法来实现三栏布局,那么侧边栏对应的元素在html文档中的位置就要在主区域的前面,但这样也导致了主体内容是最后加载的

<style>
  .container {
    height: 200px;
  }

  .left {
    float: left;
    width: 200px;
    height: 100%;
    background-color: orange;
  }

  .right {
    float: right;
    width: 300px;
    height: 100%;
    background-color: orange;
  }

  .main {
    height: 100%;
    margin-left: 200px;
    margin-right: 300px;
    background-color: lightblue;
  }
</style>

<body>
  <div class="container">
    <aside class="left"></aside>
    <aside class="right"></aside>
    <div class="main"></div>
  </div>
</body>

将三栏的元素全部浮动,利用calc计算属性控制主区域的宽度

<style>
  .container {
    height: 200px;
  }

  .left,
  .right,
  .main {
    float: left;
    height: 100%;
  }

  .left {
    width: 200px;
    background-color: orange;
  }

  .right {
    width: 300px;
    background-color: orange;
  }

  .main {
    width: calc(100% - 500px);
    background-color: lightblue;
  }
</style>

<body>
  <div class="container">
    <aside class="left"></aside>
    <div class="main"></div>
    <aside class="right"></aside>
  </div>
</body>

绝对定位

利用绝对定位,左右两栏设置为绝对定位,中间设置对应方向大小的margin的值,无需考虑HTML结构中的顺序

这种做法有个好处:就是可以把我们主要区域那一栏书写在包含块的最前面,这样有利于SEO优化,搜索引擎在读取源代码的时候会认为越靠前的元素越重要

<style>
  .container {
    position: relative;
    height: 200px;
  }
  
  .main {
    height: 100%;
    margin-left: 200px;
    margin-right: 300px;
    background-color: lightblue;
  }
  
  .left {
    position: absolute;
    top: 0;
    left: 0;
    width: 200px;
    height: 100%;
    background-color: orange;
  }
  
  .right {
    position: absolute;
    top: 0;
    right: 0;
    width: 300px;
    height: 100%;
    background-color: orange;
  }
</style>

<body>
  <div class="container">
    <div class="main"></div>
    <aside class="left"></aside>
    <aside class="right"></aside>
  </div>
</body>

flex布局

利用flex布局,左右两栏设置固定大小,中间一栏设置为flex:1;由于开启了开启了flex布局的元素的align-items属性为strench,所以其子元素的高度会自动伸展至填充父元素

<style>
  .container {
    display: flex;
    height: 200px;
  }

  .left {
    flex: 0 0 200px;
    background-color: orange;
  }

  .right {
    flex: 0 0 300px;
    background-color: orange;
  }

  .main {
    flex: 1;
    background-color: lightblue;
  }
</style>

<body>
  <div class="container">
    <aside class="left"></aside>
    <div class="main"></div>
    <aside class="right"></aside>
  </div>
</body>

圣杯布局(浮动与相对定位的结合)

利用浮动和负边距来实现。父级元素设置左右的 padding,三列均设置向左浮动,中间一列放在最前面,宽度设置为父级元素的宽度,因此后面两列都被挤到了下一行,通过设置 margin-left 负值将其移动到上一行,再利用相对定位,定位到两边

浮动元素已经脱离了文档流,所以margin-left作用与浮动元素与作用于常规流元素效果不同,如果是常规流元素,无论下一行的margin值为多少,都不会切换到上一行去;但是对于浮动元素而言,却可以轻易通过margin值跨行移动,这也是我们实现圣杯布局的重要基础

<style>
  .container {
    height: 200px;
    padding: 0 300px 0 200px;
  }

  .left,
  .right,
  .main {
    float: left;
    height: 100%;
  }

  .main {
    width: 100%;
    background-color: lightblue;
  }

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

  .right {
    position: relative;
    top: 0;
    right: -300px;
    width: 300px;
    margin-left: -300px;
    background-color: orange;
  }
</style>

<body>
  <div class="container">
    <div class="main"></div>
    <aside class="left"></aside>
    <aside class="right"></aside>
  </div>
</body>

双飞翼布局

双飞翼布局相对于圣杯布局来说,左右位置的保留是通过中间列的 margin 值来实现的,而不是通过父元素的 padding 来实现的,而且主要区域多了一层嵌套元素,导致我们可以不需要使用相对定位。但本质上来说,其也是通过浮动和外边距负值来实现的

  • 左边通过使用margin-left:-100% ,相当于中间的宽度,所以向上偏移到左侧
  • 右边通过使用margin-left:-300px,相当于自身宽度,所以向上偏移到最右侧
<style>
  .container {
    height: 200px;
  }

  .left,
  .right,
  .wrapper {
    float: left;
    height: 100%;
  }

  .wrapper {
    width: 100%;
  }

  .main {
    height: 100%;
    margin-left: 200px;
    margin-right: 300px;
    background-color: lightblue;
  }

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

  .right {
    width: 300px;
    margin-left: -300px;
    background-color: orange;
  }
</style>

<body>
  <div class="container">
    <div class="wrapper">
      <div class="main"></div>
    </div>
    <aside class="left"></aside>
    <aside class="right"></aside>
  </div>
</body>

table布局

标签用于展示行列数据,不适合用于布局。但是可以使用 display: table 来实现布局的效果

  • 先通过display: table 设置为表格,设置 table-layout: fixed 表示列宽自身宽度决定,而不是由单元格内容设定;
  • 内层的左中右通过 display: table-cell设置为表格单元
  • 左右设置固定宽度,主区域填充剩下的宽度
<style>
  .container {
    display: table;
    height: 200px;
  }

  .left,
  .right,
  .main {
    display: table-cell;
    height: 100%;
  }

  .left {
    width: 200px;
    background-color: orange;
  }

  .main {
    background-color: lightblue;
  }

  .right {
    width: 300px;
    background-color: orange;
  }
</style>

<body>
  <div class="container">
    <aside class="left"></aside>
    <div class="main"></div>
    <aside class="right"></aside>
  </div>
</body>

grid布局

将父容器设置为grid布局,grid-template-columns: 200px auto 300px; 设置三列网格其中左右分别为200px300px,中间自适应

<style>
  .container {
    display: grid;
    height: 200px;
    grid-template-columns: 200px auto 300px;
  }

  .left {
    background-color: orange;
  }

  .right {
    background-color: orange;
  }

  .main {
    background-color: lightblue;
  }
</style>

<body>
  <div class="container">
    <aside class="left"></aside>
    <div class="main"></div>
    <aside class="right"></aside>
  </div>
</body>

实现效果

上述所有方法最终实现的效果均如下图所示:

参考文章

juejin.cn/post/690553…

juejin.cn/post/709932…

juejin.cn/post/709197…