Flexbox 简明教程
Flexbox布局的目的是将我们从编写复杂 css 样式的地狱中拯救出来。但掌握Flexbox并非易事。所以,本文主要通过动画的方式介绍 Flexbox 布局的用法,让我们能够使用 Flexbox 构建更好的布局。
Flexbox 布局的中心思想是让布局更加灵活和直观。因此,Flexbox通过声明的方式让容器自己决定如何布局它的子控件 - 包括它们的自身大小和子控件间的间距。这种思想很不错,让我们来看一下在实践中是如何应用的。
在本文中,我们将会仔细介绍9个常用的 Flexbox 的属性。包括如何使用、使用后的效果等等。
#1: Display: Flex
这是我们在使用原有 css 布局的样式:
display: block
上图中有四个子的 div 被放置在一个灰色的 div 容器中。目前,每个 div 都含有默认的 display 属性 - block
。每个子div也因此占据了整行。
为了开始使用 Flexbox,我们需要让父容器 div 变成一个 flex 容器,只需更改其 display 属性:
.container {
display: flex;
}
虽然仅仅改变了一个单词,使得container容器现在拥有了 flex 的环境,它里面的子 div 就都会并排排列。
本例CodePen 地址:https://codepen.io/saymagic/pen/jzjxxV
#2: Flex Direction
Flexbox 容器包含了两条轴。主轴(main axis)和交叉轴 (cross axis),默认情况下两条轴的情况如下:
默认情况下,Flexbox 的子元素会被按照从左到右的顺序排放在主轴。这就是上个例子中我们对 container 声明display
为 flex 之后,四个子元素横向排列的原因。
通过flex-direction
属性,我们可以调换主轴:
.container {
display: flex;
flex-direction: column;
}
这里有个很重要的点需要指出:flex-direction: column
并不意味着将子元素在交叉轴上排列。而是将主轴从横向变为纵向。
flex-direction
有另外两个值可以设置:row-reverse
和column-reverse
。通过名字你一定可以猜出它们的作用,效果如下:
本例CodePen 地址: https://codepen.io/saymagic/pen/WzqJqp
#3: Justify Content
justify-content
用于控制子元素在主轴上如何对齐。其共有五个可供设置的值:
- flex-start
- flex-end
- center
- space-between
- space-around
justify-content
的默认值为flex-start,意味着子元素从开始位置向结束位置排列
.container {
display: flex;
flex-direction: row;
justify-content: flex-start;
}
需要特别注意的是:justify-content
作用的是主轴,而flex-direction
会切换主轴。
本例CodePen 地址: https://codepen.io/saymagic/pen/geNKar
#4: Align Items
如果刚刚理解了justify-content
, align-items
也会很容易理解。它用于描述元素在交叉轴上如何对齐。
align-items
也包含了五个值:
- flex-start
- flex-end
- center
- stretch
- baseline
前面三个和 justify-content
可选的值一样,这里没有什么特殊。最后两个有点特殊:
stretch
会让元素占满整个交叉轴,baseline
会使子元素的第一行文字的基线对齐。
(需要注意的是当align-items
设置为 stretch 之后,每个子元素的高度必须设置为auto
,否则,height
属性会覆盖align-items
属性)
为了更好的理解主轴和交叉轴,我们将justify-content
和align-items
结合起来看看会产生什么神奇效果:
本例CodePen 地址: https://codepen.io/saymagic/pen/XELYKx
#5: Align Self
align-self
允许子元素指定自己在交叉轴上的表现形式。如果一个子元素不指定align-self
,则会按照父布局中的align-items
参数进行排版。反之,会覆盖父布局对自己的要求,按照自身指定的值进行排版。align-self
作用在子元素上,示例代码如下:
.container {
align-items: flex-start;
}
.one {
align-self: center;
}
// Only this square will be centered.
下面的 GIF 描述的是,我们对父布局的align-items
设置为center
,flex-direction
设置为row
, 对前两个方块设置了相同的align-self
:
本例CodePen 地址:https://codepen.io/saymagic/pen/NYZBwo
#6: Flex-Basis
flex-basis
控制着一个子元素的默认大小。从下面的 GIF 中我们可以看到,flex-basis
是可以替换width
属性的:
flex-basis
和width
貌似看起来一样,那它们的区别是什么呢?主要区别在于flex-basis
作用的是我们主轴方向元素的大小。
下面我们看下,当我们将flex-basis
保持不变,但是切换主轴的方向会发生什么:
可以看到,当flex-direction
为row
时,flex-basis
相当于width
属性。当flex-direction
为column
时,flex-basis
相当于height
属性,
本例CodePen 地址: https://codepen.io/saymagic/pen/JLQBmJ
#7 Flex Grow
接下来我们看下稍微复杂一点的flex-grow
属性。首先,首先我们将所有的子元素的宽度都设置为120px:
flex-grow
属性的默认值为0,这意味着子元素不允许占据容器中剩余的空间。如果我们将每个子元素的flex-grow
属性都设置为1看看效果吧:
六个子元素共同占据了容器的整个宽度,容器本来剩余的空间被均匀地分布在每个子元素上。并且可以看到, flex-grow
会覆盖width
属性。关键的问题在于,flex-grow
的值1
代表着什么呢?我们不防将每个子元素的flex-grow
的值设置为999,效果如下:
可以看到,为每个子元素设置了1或者999都是一样的。实际上,我们可以将flex-grow
理解为子元素的放大比例,默认为0,即如果存在剩余空间,也不放大。如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
下面我们将所有子元素的flex-grow
都设置为1,变动第三个子元素的flex-grow
值:
本例CodePen 地址: https://codepen.io/saymagic/pen/pLXZYJ
#8: Flex Shrink
flex-shrink
和 flex-grow
相反,用于定义当父容器空间不够时,子元素如何压缩自己。
在下面的 GIF 中,每个子元素的flex-grow
值都设置为1,所以当父容器缩小时,每个子元素都均匀的缩小:
现在,我们单独将第三个子元素的flex-shrink
属性设置为0,这意味着第三个子元素不允许被压缩:
如我们期望的一样,当父容器逐渐变小时,第三个元素的大小并未随之改变。
本例CodePen 地址: https://codepen.io/saymagic/pen/vRqzNV
#9: Flex
flex
属性仅仅是对grow, shrink, 和 basis 三个属性的简写,默认值为0 (grow)、 1 (shrink)、 auto (basis)。比较简单,这里不做展开。
到这里,Flexbox 的常用属性就介绍的差不多了。本文主要翻译自https://medium.freecodecamp.org/an-animated-guide-to-flexbox-d280cf6afc35、https://medium.freecodecamp.org/even-more-about-how-flexbox-works-explained-in-big-colorful-animated-gifs-a5a74812b053两篇文章并做了部分的修改。
on