理解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的

相关推荐
热爱编程的小曾27 分钟前
sqli-labs靶场 less 8
前端·数据库·less
gongzemin38 分钟前
React 和 Vue3 在事件传递的区别
前端·vue.js·react.js
Apifox1 小时前
如何在 Apifox 中通过 Runner 运行包含云端数据库连接配置的测试场景
前端·后端·ci/cd
-代号95271 小时前
【JavaScript】十四、轮播图
javascript·css·css3
树上有只程序猿1 小时前
后端思维之高并发处理方案
前端
庸俗今天不摸鱼2 小时前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
黄毛火烧雪下2 小时前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox2 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞2 小时前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行2 小时前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox