常见布局类型

164 阅读8分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情

常见布局

两列布局

两栏布局一般指的就是左侧宽度固定,右侧宽度自适应 image.png

有以下几种实现方式:

1. 使用浮动布局

<template>
  <div>
    <div class="container">
      <div class="left-box">我是左边盒子</div>
      <div class="right-box">我是右边盒子</div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.container {
  width: 100%;
  .left-box {
    width: 200px;
    height: 200px;
    float: left;
    background-color: aqua;
  }
  .right-box {
    width: auto;
    height: 200px;
    background-color: bisque;
  }
}
</style>

2. 使用相对定位/绝对定位布局

相对定位

<template>
  <div>
    <div class="container">
      <div class="left-box">我是左边盒子</div>
      <div class="right-box">我是右边盒子</div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.container {
  width: 100%;
  .left-box {
    width: 200px;
    height: 200px;
    background-color: aqua;
  }
  .right-box {
    width: auto;
    height: 200px;
    background-color: bisque;
    position: relative;
    left: 200px;
    top: -200px;
  }
}

绝对定位

<template>
  <div>
    <div class="container">
      <div class="left-box">我是左边盒子</div>
      <div class="right-box">我是右边盒子</div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.container {
  width: 100%;
  position: relative;
  .left-box {
    width: 200px;
    height: 200px;
    background-color: aqua;
  }
  .right-box {
    width: auto;
    height: 200px;
    background-color: bisque;
    position: absolute;
    left: 200px;
    right: 0px;
    top: 0px;
  }
}

3. 使用flex布局

<template>
  <div>
    <div class="container">
      <div class="left-box">我是左边盒子</div>
      <div class="right-box">我是右边盒子</div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.container {
  width: 100%;
  display: flex;
  .left-box {
    width: 200px;
    height: 200px;
    background-color: aqua;
  }
  .right-box {
    flex: 1;
    height: 200px;
    background-color: bisque;
  }
}
</style>

三列布局

三栏布局一般指的是左侧宽度固定,右侧宽度固定,中间自适应

image.png

有以下几种实现方式:

1. 使用浮动布局

<template>
  <div>
    <div class="container">
      <div class="left-box">我是左边盒子</div>
      <div class="right-box">我是右边盒子</div>
      <div class="center-box">我是中间盒子</div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.container {
  width: 100%;
  .left-box {
    width: 200px;
    height: 200px;
    background-color: aqua;
    float: left;
  }
  .center-box {
    margin-left: 200px;
    margin-right: 200px;
    height: 200px;
    background-color: azure;
  }
  .right-box {
    width: 200px;
    height: 200px;
    background-color: bisque;
    float: right;
  }
}
</style>

这种布局需要注意几个问题:

  • 必须把中间盒子放在最后面(html结构中),否则会出现最右边盒子换行的情况
  • 通过设置左右边距来让中间盒子正好填上中间的空白
  • 也可以通过给中间盒子设置BFC的方式来实现
<template>
  <div>
    <div class="container">
      <div class="left-box">我是左边盒子</div>
      <div class="right-box">我是右边盒子</div>
      <div class="center-box">我是中间盒子</div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.container {
  width: 100%;
  .left-box {
    width: 200px;
    height: 200px;
    background-color: aqua;
    float: left;
  }
  .center-box {
    overflow: hidden;
    height: 200px;
    background-color: azure;
  }
  .right-box {
    width: 200px;
    height: 200px;
    background-color: bisque;
    float: right;
  }
}
</style>

2. 使用flex布局

<template>
  <div>
    <div class="container">
      <div class="left-box">我是左边盒子</div>
      <div class="center-box">我是中间盒子</div>
      <div class="right-box">我是右边盒子</div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.container {
  width: 100%;
  display: flex;
  .left-box {
    width: 200px;
    height: 200px;
    background-color: aqua;
  }
  .center-box {
    flex: 1;
    height: 200px;
    background-color: azure;
  }
  .right-box {
    width: 200px;
    height: 200px;
    background-color: bisque;
  }
}
</style>

这几种布局都存在以下几种问题:

  1. 中间元素不能先加载出来,这样用户体验不好
  2. 所有的高度都是已知的,如果高度不定,不能实现三列等高

圣杯布局

圣杯布局就是为了解决中间元素不能先加载出来的,主要实现方式就是将中间盒子放在第一位,这样就能实现先加载了,然后再用浮动定位和相对定位设置相应的位置

<template>
  <div>
    <div class="container">
      <div class="center-box">我是中间盒子</div>
      <div class="left-box">我是左边盒子</div>
      <div class="right-box">我是右边盒子</div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.container {
  margin-left: 200px;
  margin-right: 200px;
  .left-box {
    width: 200px;
    height: 200px;
    background-color: aqua;
    float: left;
    position: relative;
    left: -200px;
    margin-left: -100%;
  }
  .center-box {
    width: 100%;
    height: 200px;
    background-color: azure;
    float: left;
  }
  .right-box {
    width: 200px;
    height: 200px;
    background-color: bisque;
    float: left;
    margin-left: -200px;
    position: relative;
    right: -200px;
  }
}
</style>

双飞翼布局

双飞翼布局也是为了解决中间元素不能先加载出来的,主要实现方式就是将中间盒子用一个容器盒子套住,然后放在第一位,这样就能实现先加载了,然后再用浮动定位设置相应的位置。

<template>
  <div>
    <div class="container">
      <div class="center-container">
        <div class="center-box">我是中间盒子</div>
      </div>
      <div class="left-box">我是左边盒子</div>
      <div class="right-box">我是右边盒子</div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.container {
  width: 100%;
  .center-container {
    float: left;
    width: 100%;
  }
  .left-box {
    width: 200px;
    height: 200px;
    background-color: aqua;
    float: left;
    margin-left: -100%;
  }
  .center-box {
    margin-left: 200px;
    margin-right: 200px;
    height: 200px;
    background-color: azure;
  }
  .right-box {
    width: 200px;
    height: 200px;
    background-color: bisque;
    float: left;
    margin-left: -200px;
  }
}
</style>

圣杯布局和双飞翼布局的区别

  • 不同的就是html结构,双飞翼是在中间元素内部又设置了一个内部元素并设置它的左右margin,来排除两边元素的覆盖,而圣杯布局是直接在最外层容器上设置左右margin,来排除两边元素的覆盖。
  • 双飞翼布局可以多了一个html结构,但是可以不用设置left,right元素的定位。

flex布局实现中间元素先加载

主要实现方式就是将中间盒子放在第一位,这样就能实现先加载了。然后设置order属性将其放在第二个位置。

<template>
  <div>
    <div class="container">
      <div class="center-box">我是中间盒子</div>
      <div class="left-box">我是左边盒子</div>
      <div class="right-box">我是右边盒子</div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.container {
  width: 100%;
  display: flex;
  .left-box {
    width: 200px;
    height: 200px;
    background-color: aqua;
    order: 0;
  }
  .center-box {
    flex: 1;
    height: 200px;
    background-color: azure;
    order: 1;
  }
  .right-box {
    width: 200px;
    height: 200px;
    background-color: bisque;
    order: 2;
  }
}
</style>

flex布局实现高度不定多列等高

在实现多列布局的时候,如果高度不定的话,我们是很难实现等高的(以前是采用负margin-bottom和正padding-bottom对冲实现,这种方式非常复杂,这里我们推荐使用flex布局)

<template>
  <div>
    <div class="container">
      <div class="center-box">我是中间盒子我是中间盒子我是中间盒子我是中间盒子我是中间盒子</div>
      <div class="left-box">我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子我是左边盒子</div>
      <div class="right-box">我是右边盒子</div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.container {
  width: 100%;
  display: flex;
  .left-box {
    width: 200px;
    background-color: aqua;
    order: 0;
  }
  .center-box {
    flex: 1;
    background-color: azure;
    order: 1;
  }
  .right-box {
    width: 200px;
    background-color: bisque;
    order: 2;
  }
}

效果如下:

1666189138578.png

网易考拉带边框的多列布局

image.png

实现步骤

1. 最外层盒子设置固定宽度,水平居中

width: 1100px;
margin: 10px auto;   // 水平居中的核心代码
height: 168px;
background-color: red;

2. 里面每个盒子设置宽度,浮动,一行排列

这里需要说明的是为什么不使用inline-block实现一行排列,因为inline-block里面会带有内联元素的特性,导致一行排列的时候很难控制居中等对齐。因此涉及到多列一行展示的时候我们首选浮动,flex布局,grid布局,或者columns流式布局。然后结合实际项目兼容性来考虑选择适合项目场景的布局方式。

width: 220px;
height: 168px;
background-color: lightcyan;
float: left;

3. 为了设置边框,直接给每个盒子增加边框

border: 1px solid lightgray;

image.png

4. 解决边框重叠和最后一个元素挤下来的问题

  • 解决边框重叠

    通常我们解决边框重叠的问题是给相邻两个元素中的左边元素设置右边框,右边元素的左边框设置一个none。或者反过来,右边元素的左边框设置一个左边框,左边元素的右边框设置一个none.但是在很多元素中这样设置其实很很复杂的,需要根据元素的位置区分(是奇数还是偶数)。 下面我们采用一共更简单的方式,将右边的元素设置一个负外边框,这样两个元素就会重叠起来,这样你看到的边框就是一个边框。

    margin-left: -1px;
    

    image.png

  • 解决最后一个元素被挤下来的问题

    最后一个元素被挤下来的原因很简单,因为容器的宽度是1100px。每个盒子的宽度是220px + boder(2) = 222px。这样五个盒子的宽度加起来大于1100px。所以最后一个元素就会被挤到下一行。因此只需要设置box-sizing为border-box就可以了

    box-sizing: border-box;
    

    但是这时候还有一个问题,就是重叠了之后看到的每个盒子的宽度其实是变小了的,这样五个盒子的总宽度是要比容器宽度小。

    image.png

  • 解决盒子不能和容器重叠问题

    盒子的宽度设置的是220px,除去边框的宽度其实内容的宽度只有118px。由于每个元素都重叠了1px, 除了最后一个元素,所有的元素都被遮挡了1px。因此需要把每个元素的宽度都加上1px。

    width: 221px;
    

    这时候看起来好像没有问题了,但是因为第一个盒子也往左边移了1px,而且其实盒子占据的总宽度是要比容器的宽度多1px。因此我们需要做两件事,第一,将盒子往右边移动1px的距离,第二给其中一个盒子的宽度减少1px,因为我们可以看出只有最后一个盒子没有被遮挡,因此可以减少最后一个盒子的宽度。总的来说,就是给第一个盒子设置margin-left: 0;归位。给最后一个元素设置220px的实际宽度。

    .first {
      margin-left: 0px;
    }
    .last {
      width: 220px;
    }
    

    image.png

完整代码

<div class="container">
  <div class="box-wrap">
    <div class="box first">我是第1个盒子</div>
    <div class="box">我是第2个盒子</div>
    <div class="box">我是第3个盒子</div>
    <div class="box">我是第4个盒子</div>
    <div class="box">我是第5个盒子</div>
  </div>
</div>

.container {
  width: 1100px;
  margin: 10px auto;
  height: 168px;
  background-color: red;
  .box-wrap {
    width: 100%;
    height: 168px;
    background-color: aquamarine;
    .box {
      width: 221px;
      height: 168px;
      background-color: lightcyan;
      float: left;
      border: 1px solid lightgray;
      box-sizing: border-box;
      margin-left: -1px;
    }
    .first {
      margin-left: 0px;
    }
    .last {
      width: 220px;
    }
  }
}