理解flex布局

这篇文章不会具体讲各个属性有什么效果,只会简单介绍下部分属性。相反,这篇文章主要讲的是我是怎么理解flex布局,在我看来,属性的意义是什么,这个命名有什么含义。这篇文章建议配置这个网站一起使用

在文章开始前,如果你熟悉flex,不妨先看看下几个问题

  1. 不使用align-itemsalign-self能让flex布局的元素水平垂直居中吗?
  2. 在flex布局使用justify-itemsjustify-self有什么效果?
  3. flex布局能做到一个元素靠左,其他元素靠右的效果吗

假设你是设计师

没什么能比作者本人更了解自己的作品了,身临其境无疑是最好的理解方式。所以现在假设目前没有flex或者grid布局,而你正在制定css标准,现在希望设计一个水平方向的布局,能在一行中排列多个块级元素。

水平布局的问题

在互联网上,通常有个常识,如果垂直方向内容溢出页面的话,通常可以通过滚动页面来查看溢出的内容。

但水平方向溢出却比较少见,一般来说,水平滚动不符合人们的阅读习惯,现代设备对应水平滚动的操作也不太友好,如果没有明确的指示,用户很难意识到页面可以水平滚动。所以在设计布局时,你要避免内容溢出容器而且出现滚动。

开始

为了适应各种设备的宽度并避免溢出,你设计的布局要非常灵活 地处理宽度,flexible这个单词形容这个布局再合适不过了。为了方便书写,你决定用flex来命名你的布局。

现在你确定了你布局的名字(flex),你很快设计出了第一版,目前元素只需要在水平方向上靠右,垂直方向靠上就好。我们用A、B、C这三个不等高的元素做个演示。

css 复制代码
.content {
  height: 200px;
  display: flex;
}
.item {
  background-color: red;
  width: 100px;
}
.a {
  height: 100px;
}
.b {
  height: 50px;
}
.c {
  height: 150px;
}
html 复制代码
<div class="content">
  <div class="item a">A</div>
  <div class="item b">B</div>
  <div class="item c">C</div>
</div>

flex-basis

现在这三个元素宽度都是100px,并且能完全展示,但就像之前说的,我们的宽度是不定的,布局的元素可能需要随着容器的宽度变化,这需要一个针对flex布局的属性。这块很容易理解,使用flex-basis来设置元素在这个布局的默认宽度,然后使用flex-growflex-shrink来控制元素随着容器宽度变化的幅度。这部分不是本文的重点,就略过了。

单行

作为设计师,你打算一步步来,先处理完单行展示的情况。

justify-content

再看我们开始的例子,看看有什么可以改进的地方。

你发现目前布局中右侧还有一块空间,而且元素却都集中在左侧,这个看上去不太美观。所以你打算先对这块做优化,让元素在有额外空间时能展示得更灵活些,大概有两个方案。

  1. 手动将布局分割成多个空间,手动设置每个空间的大小,每个元素只能占据一个或多个空间。这样处理非常灵活,但需要预先设置每行的元素个数。
  2. 让布局内的元素按照预定的规则对齐,例如让元素在容器内均匀分布,或者让元素在容器内居中展示。这样不需要预先设置每行的元素个数,但是不够灵活。

每个方案都有优缺点,选哪个都没什么问题,当然最后flex使用了第二个方案,而第一个方案交给了grid

现在确定了布局的对齐方式,需要给它起个名字。因为这个属性控制了布局内的元素空间 ,也就是布局的内容 ,自然联想content这个单词,但你还需要加个修饰词.毕竟content范围比较空泛,你打算找个有排序 或者对齐 含义的单词,比如justify,组合起来就是justify-content,这个名字看起来命名很合理。

后面是确认各类规则的事情了,就不具体介绍了,可以点这里了解。现在尝试下在.content类中加上justify-content: space-between,让布局均匀排列每个元素。

align-self

继续看看布局还有什么需要提升的地方,在垂直方向上,A、B、C三个元素下方都还有空间,这个看上去也不太美观。所以你下个目标是控制元素在容器内垂直方向的展示位置。一般来说,我们容器的高度由最高的元素决定,但这里容器自己设置了高度,所以所有元素下方都存在空间。

现在,你希望A元素能垂直居中,你会怎么办呢?你也许想说给A元素加个新属性,但在这个例子中有些大材小用了,你其实可以使用margin实现垂直居中

css 复制代码
.a {
  margin-block: auto;
  height: 100px;
}

事实就是真实的flex标准,这块可以通过marginheight组合做出类似的效果。但最后你还是觉得加个属性进行控制,一方面是为了语意更加清晰,另一方也是为了一些flex布局独特的对齐方式,例如根据布局的文字对齐(baseline)。

所以又到了命名时间了,含义是控制元素自身在垂直方向的对齐方式。最后的结果大家应该情况,是align-self, 是alignment的缩写self 的组合,校准自身的意思。但在我看来,align没有表达出方向的含义,和justify没太多的区分,不算一个特别好地命名。在记忆名字时,你需要在脑海里将justify与水平方向关联,align与垂直方向关联。

后面又是确认各类规则的事情了,就不具体介绍了,可以点这里了解。现在试下把a类的margin-block: auto;改为align-self: center;,也会是同样的效果。

当然,给每个元素都单独设置align-self不免有些麻烦,你增加一个align-item的属性,可以给flex布局内所有的元素设置了一个默认值。

换行

现在单行的内容处理差不多了,是时候进一步处理下换行问题了,水平布局总是不可避免重新内容超出宽度的问题,这时候需要换行展示。

像文字一样,你把换行的权限分了用户,增加了一个flex-wrap属性。

为了演示换行效果,需要增加几个元素,现在的html和css应该是这样

css 复制代码
.content {
  height: 400px;
  display: flex;
  justify-content: space-between;
  align-content: start;
  flex-wrap: wrap;
}
.item {
  background-color: red;
  width: 100px;
}
.a {
  height: 100px;
}
.b {
  height: 50px;
}
.c,
.d,
.e,
.f {
  height: 150px;
}
html 复制代码
<div class="content">
  <div class="item a">A</div>
  <div class="item b">B</div>
  <div class="item c">C</div>
  <div class="item d">D</div>
  <div class="item e">E</div>
  <div class="item f">F</div>
</div>

注意,这里加了align-content: start只是为了更好地说明,因为默认情况下多行会自动分配空间,但毕竟我们现在假设没有flex布局,所以我们让多行之间向上靠齐,这样更符合我们的假设。

对于新的一行,只需要按上面的规则原样处理就好,现在我们只关注每一行之间的关系。

align-content

现在让我们做个抽象处理,我们并不关注行内的元素,我们只关系行之间的关系,那么把一行当成一这个整体看待,现在就类似于在处理这种情况。

是不是感觉似曾相识,没有?别着急,让我们逆时针旋转90度再看下。

看出来了吗?这个和我们介绍justify-content时的例子非常类似,只是这次由水平方向改为了垂直方向

既然问题类似,那么自然也能用类似的方案处理,只是方向有些变化。所以你打算重复justify-content的思路,属性值也是基本可以复用,只需要起个好名字,正好之前提到align有垂直方向的含义,那就取个类似的名字:align-content

事实上align-contentjustify-content也是有些区别的,主要是在文字的展示上,所以属性值也有部分差异,可以查看这里

现在尝试在content类中加入align-content: space-between

justify-self

既然align-content是基本沿用justify-content的设计,那么是不是有justify-self属性,也可以沿用align-self呢。的确,css有justify-self属性,但在flex布局中这块并不会生效。

回想下我们为什么引入了align-self,是因为处理单行时,垂直方向上的元素还有空余空间。那现在换到多行的情况下,justify-self就是处理水平方向上每行,但就像上面图片展示的,每行宽度都是100%,没有空余空间,没办法做到水平移动,所以justify-self不会生效。同样的,justify-items也不会生效。

方向

在上面介绍flex时,我们一直假设单行方向是水平从左到右的,但在介绍align-content时,我们把每一行抽象成一个元素,就类似于垂直方向从上到下的单行布局。所以你可以发现这个布局不必局限在水平方向。

如果你之前学过flex,应该有听过主轴和交错轴的概念,现在我们也是时候引入这个概念了。当然你不必过度纠结这个概念,引入轴是为了更好地表示布局的方向,要是觉得这个说法不能帮你确认布局的方向,你也可以抽象成其他概念。

主轴,可以理解是单行时元素的排列方向,默认情况下和文本方向一致的,在中文环境下是水平从左到右。

交错轴,垂直于主轴的轴,他的方向是由flex-wrap控制的。flex-wrap: wrap是主轴顺时针旋转90度,flex-wrap: wrap-reverse是主轴逆时针旋转90度。

引入了轴的概念后,我们还需要一个属性实现确认主轴的方向,你起了个意义比较明确的单词flex-direction。为了适应不同语言的习惯,你打算让这个属性与书写方向绑定。flex-direction: row就是我们文字书写的方向(中文是从左到右的水平轴),而flex-direction: column就是我们多行文字换行的方向(中文是从上到下的垂直轴)。

最后

其实本来是打算和grid合一起写一篇的,但时间有限,有时间后面再补充一篇grid的

相关推荐
酷酷的阿云1 分钟前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:137971205873 分钟前
web端手机录音
前端
齐 飞9 分钟前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
神仙别闹26 分钟前
基于tensorflow和flask的本地图片库web图片搜索引擎
前端·flask·tensorflow
GIS程序媛—椰子1 小时前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_0011 小时前
前端八股文(一)HTML 持续更新中。。。
前端·html
ZL不懂前端1 小时前
Content Security Policy (CSP)
前端·javascript·面试
木舟10092 小时前
ffmpeg重复回听音频流,时长叠加问题
前端
王大锤43912 小时前
golang通用后台管理系统07(后台与若依前端对接)
开发语言·前端·golang
我血条子呢2 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js