flex弹性布局的应用

2023-09-18 11:49 孙水迪 794

1.什么是flex弹性布局

flex是什么,有哪些样式,可以实现什么效果,这里不多赘述,可以阅读这篇文章学习,里面非常详尽:https://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

本文假设读者已经对flex的各个属性有了一定的了解

2.如何使用

在flex布局里,常用的属性有6个,分别为display,flex-direction,justify-content,align-items,flex-wrap,flex,除了flex是用在子标签里的,其余五个都用在父标签里,分别描述了布局的不同属性

display描述了这是flex布局

flex-direction描述了布局的方向

justify-content描述了布局垂直方向的左右居中情况

align-items描述了布局方向的左右居中情况

flex-wrap描述了子标签宽度超出父标签的时候,父标签该如何管理子标签

flex描述了子标签如何管理自己的宽度

其中前4个属性最为常用,后2个属性则按需使用,灵活使用这6个属性,足以实现90%以上的布局

{
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}

但是使用时往往需要同时编写如上4个属性,在页面有较多层级嵌套时,会显得非常重复

如果将这4个属性放在style里,则html会被这4个属性占满,喧宾夺主

如果放在诸如“title”,“main-box”等包含块意义的class里,则会显得可读性低下,看到“title”这个class名称,只会知道这个块是title,但无法知道title里面的标签的布局方式,而通过class的点击跳转来查看其具体属性,这个功能目前ide的支持又比较差,当一个项目里有多个“title”class时,到底跳转到哪一个“title”会成为一个问题

因此,为flex布局单独编写一个样式类,命名为“flex.css”,放在全局样式里,如下命名,使用时直接调用,则可以解决上面的这些全部问题,专注于布局

.flex-column-center-start {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
}

解释一下上面这个class名称的意义,flex代表这是弹性布局,column代表布局方向为从上至下,center代表在布局垂直方向上居中,start代表在布局方向上靠前

简单编写一个示例

<div class="flex-column-start-center" style="width: 400px;height: 400px;background: darkgrey">
  <div style="width: 100px;height: 100px;background: gold"></div>
  <div style="width: 50px;height: 50px;background: beige"></div>
  <div style="width: 200px;height: 200px;background: darkseagreen"></div>
</div>

轻松实现了居中且从上往下摆放的页面需求

常用的flex.css文件如下,该文件为作者原创,好用非常,可以理清布局思路,极大提升布局效率

.flex-row-start-start {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: flex-start;
}
.flex-row-start-center {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
}
.flex-row-start-end {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: flex-end;
}
.flex-row-between-start {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: flex-start;
}
.flex-row-between-center {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
}
.flex-row-between-end {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: flex-end;
}

.flex-row-around-center {
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  align-items: center;
}

.flex-row-around-start {
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  align-items: flex-start;
}

.flex-column-center-start {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
}
.flex-row-center-center {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}

.flex-row-end-center {
  display: flex;
  flex-direction: row;
  justify-content: flex-end;
  align-items: center;
}

.flex-column-center-end {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-end;
}


.flex-column-start-start {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-start;
}
.flex-column-start-center {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
}

.flex-column-start-end {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-end;
}
.flex-column-between-start {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: flex-start;
}


.flex-column-center-stretch {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: stretch;
}

.flex-column-center-center {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.flex-column-round-start {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: flex-start;
}
.flex-column-round-center {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center;
}

3.更多示例

上文中只展示了一个比较基础的示例,但是flex布局可以作为规则布局的究极解决方案,实际应用自然不止于此,下面展示更多示例,在引入flex.css,示例代码可以在运行后查看效果,各个块我都设置了背景色

上图是知乎热榜页面,其布局非常规则,分析完这个结构后就可以用flex完美解决,当然,实际知乎在上下滑动时会有更多效果,这里暂且忽略

  • 首先主体内容在页面居中
<div class="flex-row-center-center" style="width: 100%;height: 100vh;">
  <div style="width: 800px;height: 100%;background: gray">
    这里放主体
  </div>
</div>

使用flex-row-center-center让主体内容居中,并设置高度为100%

  • 主体内内容为左右各占一定部分,并且靠上
<div class="flex-row-center-center" style="width: 100%;height: 100vh;">
  <div class="flex-row-between-start" style="width: 800px;height: 100%;background: gray;overflow-y:auto;">
    <div style="flex: 1;height:100%;background: ghostwhite">
      帖子
    </div>
    <div style="width: 200px;overflow-y:auto;height:100%;background: gainsboro">
      我的
    </div>
  </div>
</div>

使用flex-row-between-start布局左右内容

“我的”部分宽度固定,“帖子”部分的宽度则使用flex:1来占满剩余部分

  • 左侧内容为标题栏+置顶+帖子的形式排列
<div class="flex-row-center-center" style="width: 100%;height: 100vh;">
  <div class="flex-row-between-start" style="width: 800px;height: 100%;background: gray;overflow-y:auto;">
    <div class="flex-column-start-start" style="flex: 1;height:100%;background: ghostwhite">
      <div style="width: 100%;height: 60px">标题tab</div>
      <div style="width: 100%;height: 60px">置顶</div>
      <div style="flex: 1;width:100%;background: bisque;">帖子</div>
    </div>
    <div style="width: 200px;overflow-y:auto;height:100%;background: gainsboro">
      我的
    </div>
  </div>
</div>

使用flex-column-start-start使标题,置顶和帖子从上往下排列,并在子标签里设置width:100%占满宽度,这时,父标签使用flex-column-start-center也是一样的效果,毕竟左右可以100%了,无论居中靠右还是靠左都是一个效果

  • 帖子内容分为序号,正文和图片
<div class="flex-row-center-center" style="width: 100%;height: 100vh;">
  <div class="flex-row-between-start" style="width: 800px;height: 100%;background: gray;overflow-y:auto;">
    <div class="flex-column-start-center" style="flex: 1;height:100%;background: ghostwhite">
      <div style="width: 100%;height: 60px">标题tab</div>
      <div style="width: 100%;height: 60px">置顶</div>
      <div class="flex-column-start-start" style="flex: 1;width:100%;background: bisque;">
        <div class="flex-row-between-start" style="width: 100%">
          <div style="width: 30px;background: red">序号</div>
          <div class="flex-column-start-start" style="flex: 1;background: yellow">
            <div>标题</div>
            <div>正文</div>
            <div>热度</div>
          </div>
          <div style="width: 200px;height: 100px;background: blue">图片</div>
        </div>
      </div>
    </div>
    <div style="width: 200px;overflow-y:auto;height:100%;background: gainsboro">
      我的
    </div>
  </div>
</div>

使用flex-row-between-start使序号,正文,图片左右排列,正文中使用flex:1占满中间区域,这时,父标签使用flex-row-start-start也是一样的效果,毕竟左右被占满了,无论怎么描述垂直方向的居中情况都是相同的结果

正文中则使用flex-column-start-start来由上至下的依次摆放标题,正文和热度

如果有的帖子没有图片,则可以去掉图片部分,因为正文使用了flex:1,会自动占满图片的部分

  • “我的”部分布局

思路都一样,由外向内分析布局结构即可,这里不再示例

4.特殊用法

  • 文本居中

flex-row-center-center可以轻易是使文本居中,当然,flex-column-center-center也有一样的效果

<div class="flex-column-center-center" style="width: 200px;height: 100px;background: gray">
 我是居中的文字
</div>

  • 设置背景

通过flex-row-start-start和margin-left: -100%,可以设置背景

<div class="flex-row-start-start" style="width: 200px;height: 100px">
  <div style="width: 100%;height: 100%;background: gray">
  </div>
  <div class="flex-row-center-center" style="width: 100%;height: 100%;margin-left: -100%">
    我的下面有背景
  </div>
</div>

  • 右上角红点

同样通过margin即可达成

<div class="flex-row-start-start" style="width: 200px;height: 100px;background: gray;margin-top: 100px">
  <div class="flex-row-center-center" style="width: 100%;height: 100%;">
    !@#¥%……&*()
  </div>
  <div style="width: 20px;height: 20px;border-radius:10px;background: red;margin-top: -10px;margin-right: -10px"></div>
</div>