CSS中的布局汇总


更新记录

  • 2023-09-18:对于“两栏和三栏布局”作了补充。

浮动布局

详见CSS中的浮动与定位 | QT-7274 (qblog.top)

定位布局

详见CSS中的浮动与定位 | QT-7274 (qblog.top)

Flex布局

详见CSS中的盒子模型 | QT-7274 (qblog.top)

Grid布局

网格布局(Grid)是最强大的CSS布局方案,对于早期的浏览器版本兼容性不是很好,但是截止2023年,大部分浏览器已经支持Grid布局:

image-20230902194840568

基本概念

image-20230902195002914

容器属性

grid-template-*

你想要多少行或者列,就填写相应属性值的个数,不填写,自动分配。

image-20230902195230253

grid-template-* 相关
  1. repeat(),第一个参数是重复的次数,第二个参数是所要重复的值

    grid-template-columns: 100px 100px 100px;
    
    grid-template-columns: repeat(3, 100px);
  2. auto-fill,有时,单元格的大小是固定的,但是容器的大小不固定,这个属性就会自动填充。

    grid-template-columns: repeat(auto-fill, 100px);
  3. fr,为了方便表示比例关系,网格布局提供了fr关键字(fraction的缩写,意为“片段”)。

    grid-template-columns: repeat(4, 1fr);
  4. minmax(),函数产生一个长度范围,表示长度就在这个范围之中,它接受两个参数,分别为最小值和最大值。

    grid-template-columns: 1fr minmax(150px, 1fr);
  5. auto,表示由浏览器自己决定长度。

    grid-template-columns: 100px auto 100px;
  6. 网格线,可以用方括号定义网格线名称,方便以后的引用

    grid-template-columns: [c1] 100px [c2] 100px [c3] 100px [c4];

row-gap/column-gap

一句话解释就是, item(项目)相互之间的距离

row-gap:行间距

column-gap:列间距

gap:行间距+列间距

grid-template-areas

一个区域由单个或多个单元格组成,由你决定 (具体使用,需要在项目属性里面设置)

grid-template-areas:

image-20230902202105998image-20230902202119329image-20230902202136363

  1. 区域不需要利用,则使用"点"(.)表示。
  2. 区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为区域名-start,终止网格线自动命名为区域名-end。

grid-auto-flow

划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是“先行后列”, 即先填满第一行,再开始放入第二行 (就是子元素的排放顺序

image-20230902203207082

grid-auto-flow相关

image-20230902203408916

dense表示尽可能地填充空隙,以达到更好的利用空间的效果。

justify-items(水平方向) / align-items (垂直方向)

设置单元格内容的水平和垂直的对齐方式

justify-items: start | end | center | stretch;

  • justify-items: start;

    image-20230902203720586

  • justify-items: end;

    image-20230902203735630

  • justify-items: center;

    image-20230902203749326

  • justify-items: stretch;

    image-20230902203807254

    同理align-items

place-items属性是align-items属性和justify-items属性的合并简写形式。

place-items: <align-items> <justify-items>;

justify-content (水平方向) / align-content (垂直方向)

设置整个内容区域的水平和垂直的对齐方式

justify-content: start | end | center | stretch | space-around | space-between | space-evenly; align-content: start | end | center | stretch | space-around | space-between | space-evenly;

  • justify-content: center;

    image-20230902204800259

  • justify-content: space-around;

    image-20230902204826293

  • align-content: center;

    image-20230902204845615

  • align-content: space-around;

    image-20230902204925338

grid-auto-columns / grid-auto-rows

用来设置多出来的项目宽和高

image-20230902205504175

项目属性

grid-column-start / grid-column-end / grid-row-start / grid-row-end

一句话解释,用来指定item的具体位置, 根据在哪根网格线

image-20230902205750876

image-20230902205918739

从当前列开始,跨越2个网格列,网格项目将占据当前列及其后续的一列,总共跨越两列:

image-20230902210105727

grid-column / grid-row

grid-column属性是grid-column-startgrid-column-end的合并简写形式, grid-row属性是grid-rowstart属性和grid-row-end的合并简写形式

image-20230902210244338

grid-area

指定项目放在哪一个区域

image-20230902210311799

grid-area属性还可用作grid-row-startgrid-column-startgrid-row-endgrid-column-end的合并 简写形式,直接指定项目的位置 grid-area: <row-start> / <column-start> / <row-end> / <column-end>;

image-20230902210749517

justify-self / align-self / place-self

justify-self属性设置单元格内容的水平位置(左中右),跟justify-items属性的用法完全一致, 但只作用于单个项目 (水平方向) align-self属性设置单元格内容的垂直位置(上中下),跟align-items属性的用法完全一致, 也是只作用于单个项目 (垂直方向)

justify-self: start | end | center | stretch;

image-20230902210937908

align-self: start | end | center | stretch;

image-20230902211020608

place-self属性是align-self属性和justify-self属性的合并简写形式 place-self: center center;

两栏布局

两栏布局实现效果就是将页面分割成左右宽度不等的两列,宽度较小的列设置为固定宽度,剩余宽度由另一列撑满

比如 Ant Design 文档,蓝色区域为主要内容布局容器,侧边栏为次要内容布局容器

这里称宽度较小的列父元素为次要布局容器,宽度较大的列父元素为主要布局容器

img

margin实现

实现思路也非常的简单:

  • 使用 float 左浮左边栏
  • 右边模块使用 margin-left 撑出内容块做内容展示
  • 为父级元素添加BFC,防止下方元素飞到上方内容

代码如下:

<style>
    .box{
        overflow: hidden; 添加BFC
    }
    .left {
        float: left;
        width: 200px;
        background-color: gray;
        height: 400px;
    }
    .right {
        margin-left: 210px;
        background-color: lightgray;
        height: 200px;
    }
</style>
<div class="box">
    <div class="left">左边</div>
    <div class="right">右边</div>
</div>

还有一种更为简单的使用则是采取:flex弹性布局

overflow实现

.box {
 height: 200px;
}

.box > div {
  height: 100%;
}

.box-left {
  width: 200px;
  float: left;
  background-color: blue;
}

.box-right {
  overflow: hidden; 
  background-color: red;
}

flex弹性布局

<style>
    .box{
        display: flex;
    }
    .left {
        width: 100px;
    }
    .right {
        flex: 1;
    }
</style>
<div class="box">
    <div class="left">左边</div>
    <div class="right">右边</div>
</div>

flex可以说是最好的方案了,代码少,使用简单

注意:flex容器的一个默认属性值:align-items: stretch;

这个属性导致了列等高的效果。 为了让两个盒子高度自动,需要设置: align-items: flex-start

三栏布局

实现三栏布局中间自适应的布局方式有:

  • 两边使用 float,中间使用 margin
  • 两边使用 absolute,中间使用 margin
  • 两边使用 float 和负 margin
  • display: table 实现
  • flex实现
  • grid网格布局

两边使用 float,中间使用 margin

需要将中间的内容放在html结构最后,否则右侧会呈现在中间内容的下方

实现代码如下:

<style>
    .wrap {
        background: #eee;
        overflow: hidden; <!-- 生成BFC,计算高度时考虑浮动的元素 -->
        padding: 20px;
        height: 200px;
    }
    .left {
        width: 200px;
        height: 200px;
        float: left;
        background: coral;
    }
    .right {
        width: 120px;
        height: 200px;
        float: right;
        background: lightblue;
    }
    .middle {
        margin-left: 220px;
        height: 200px;
        background: lightpink;
        margin-right: 140px;
    }
</style>
<div class="wrap">
    <div class="left">左侧</div>
    <div class="right">右侧</div>
    <div class="middle">中间</div>
</div>

原理如下:

  • 两边固定宽度,中间宽度自适应。
  • 利用中间元素的margin值控制两边的间距
  • 宽度小于左右部分宽度之和时,右侧部分会被挤下去

这种实现方式存在缺陷:

  • 主体内容是最后加载的。
  • 右边在主体内容之前,如果是响应式设计,不能简单的换行展示

两边使用 absolute,中间使用 margin

基于绝对定位的三栏布局:注意绝对定位的元素脱离文档流,相对于最近的已经定位的祖先元素进行定位。无需考虑HTML中结构的顺序

<style>
  .container {
    position: relative;
  }
  
  .left,
  .right,
  .main {
    height: 200px;
    line-height: 200px;
    text-align: center;
  }

  .left {
    position: absolute;
    top: 0;
    left: 0;
    width: 100px;
    background: green;
  }

  .right {
    position: absolute;
    top: 0;
    right: 0;
    width: 100px;
    background: green;
  }

  .main {
    margin: 0 110px;
    background: black;
    color: white;
  }
</style>

<div class="container">
  <div class="left">左边固定宽度</div>
  <div class="right">右边固定宽度</div>
  <div class="main">中间自适应</div>
</div>

实现流程:

  • 左右两边使用绝对定位,固定在两侧。
  • 中间占满一行,但通过 margin和左右两边留出10px的间隔

两边使用 float 和负 margin

<style>
  .left,
  .right,
  .main {
    height: 200px;
    line-height: 200px;
    text-align: center;
  }

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

  .main {
    margin: 0 110px;
    background: black;
    color: white;
  }

  .left,
  .right {
    float: left;
    width: 100px;
    margin-left: -100%;
    background: green;
  }

  .right {
    margin-left: -100px; /* 同自身宽度 */
  }
</style>

<div class="main-wrapper">
  <div class="main">中间自适应</div>
</div>
<div class="left">左边固定宽度</div>
<div class="right">右边固定宽度</div>

实现过程:

  • 中间使用了双层标签,外层是浮动的,以便左中右能在同一行展示
  • 左边通过使用负 margin-left:-100%,相当于中间的宽度,所以向上偏移到左侧
  • 右边通过使用负 margin-left:-100px,相当于自身宽度,所以向上偏移到最右侧

缺点:

  • 增加了 .main-wrapper 一层,结构变复杂
  • 使用负 margin,调试也相对麻烦

使用 display: table 实现

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

<style>
  .container {
    height: 200px;
    line-height: 200px;
    text-align: center;
    display: table;
    table-layout: fixed;
    width: 100%;
  }

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

  .left,
  .right {
    width: 100px;
    background: green;
  }

  .main {
    background: black;
    color: white;
    width: 100%;
  }
</style>

<div class="container">
  <div class="left">左边固定宽度</div>
  <div class="main">中间自适应</div>
  <div class="right">右边固定宽度</div>
</div>

实现原理:

  • 层通过 display: table设置为表格,设置 table-layout: fixed`表示列宽自身宽度决定,而不是自动计算。
  • 内层的左中右通过 display: table-cell设置为表格单元。
  • 左右设置固定宽度,中间设置 width: 100% 填充剩下的宽度

使用flex实现

利用flex弹性布局,可以简单实现中间自适应

代码如下:

<style type="text/css">
    .wrap {
        display: flex;
        justify-content: space-between;
    }

    .left,
    .right,
    .middle {
        height: 100px;
    }

    .left {
        width: 200px;
        background: coral;
    }

    .right {
        width: 120px;
        background: lightblue;
    }

    .middle {
        background: #555;
        width: 100%;
        margin: 0 20px;
    }
</style>
<div class="wrap">
    <div class="left">左侧</div>
    <div class="middle">中间</div>
    <div class="right">右侧</div>
</div>

实现过程:

  • 仅需将容器设置为display:flex;
  • 盒内元素两端对其,将中间元素设置为100%宽度,或者设为flex:1,即可填充空白
  • 盒内元素的高度撑开容器的高度

优点:

  • 结构简单直观
  • 可以结合 flex的其他功能实现更多效果,例如使用 order属性调整显示顺序,让主体内容优先加载,但展示在中间

grid网格布局

代码如下:

<style>
    .wrap {
        display: grid;
        width: 100%;
        grid-template-columns: 300px auto 300px;
    }

    .left,
    .right,
    .middle {
        height: 100px;
    }

    .left {
        background: coral;
    }

    .right {
        background: lightblue;
    }

    .middle {
        background: #555;
    }
</style>
<div class="wrap">
    <div class="left">左侧</div>
    <div class="middle">中间</div>
    <div class="right">右侧</div>
</div>

flex弹性布局一样的简单


文章作者: QT-7274
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 QT-7274 !
评论
  目录