flex的布局原理:
- 首先根据flex-direction确定主轴以及方向:row、row-reverse、column、column-reverse。以下主轴均为row。
- 然后确定flex容器(父元素)的宽度,根据flex项目(子元素)的flex-basis与width(前者优先级大)确定每个flex项目的宽度。
- 判断flex容器的宽度与各个flex项目的宽度之和的大小关系:
- 如果flex容器宽度更大
- 如果flex容器的flex-wrap为nowrap
- 根据每个flex项目的flex-grow按比例来分配剩余的空间
- 如果flex-grow都为0,则每个flex项目宽度不变,有剩余空间,因此根据flex容器的justify-content在这一行中进行对齐。
- 如果flex-grow有一个不为0,则剩余空间比分配完。此时flex容器的justify-content则不起作用,因为没有剩余空间进行对齐。
- 根据每个flex项目的flex-grow按比例来分配剩余的空间
- 如果flex容器的flex-wrap为wrap,则flex-wrap没有任何效果,也就不会换行。
- 如果flex容器的flex-wrap为nowrap
- 如果flex容器宽度更小
- 如果flex容器的flex-wrap为nowrap,flex容器的justify-content无效
- 根据每个flex项目的flex-shrink按比例减小flex项目的宽度。
- 如果flex-shrink都为0,则每个项目都不会缩小,子元素超出父元素。因此flex容器的justify-content无效。
- 如果flex-shrink有一个不为0,则按比例缩小相关的flex项目,直到宽度之和与flex容器宽度相等。此时justify-content无效。
- 根据每个flex项目的flex-shrink按比例减小flex项目的宽度。
- 如果flex容器的flex-wrap为nowrap,flex容器的justify-content无效
- 如果flex容器宽度更大
- 设置单个元素在侧轴的对齐方式:如果flex项目的align-self存在,则根据此属性控制该项目在当前行中的对齐方式,如果不存在align-self属性,则根据flex容器的align-items来控制flex项目的对齐方式,align-items默认为stretch(当项目没有设置高度时,填充整行高度)。
- 由于在wrap的时候会出现多行,所以这里会设置flex容器中的多行的对齐方式:根据flex容器中的align-content属性设置多行的对齐方式。比如center会将所有的行集中起来并排列在flex容器中间。如果flex-wrap为nowrap,此属性失效。
flex与绝对定位以及相对定位之间的关系
如果将flex容器中的子元素设置为绝对定位,则该子元素脱离正常文档流,不会参与到flex的布局规则中,而只会根据left与top根据视口进行定位。
如果将flex容器中的子元素设置为相对定位,则该子元素不会脱离正常文档流,先参与flex的布局规则确定其位置之后,再根据left与top相对于flex布局之后的位置进行调整,还是会占据原来的位置,即其他flex项目位置不会变化。
注:如果一个元素脱离文档流,那么它不再占据文档流的空间,后面的元素会填补此空间。
HTML
const PlaceHolder = <div className='placeholder'>block</div>
<div>
<div>basic</div>
<div className = 'flex-basic-container'>
<div className = 'flex-basic-item' style={{height:"50px"}}>{PlaceHolder}</div>
<div className = 'flex-basic-item' style={{height:"80px"}}>{PlaceHolder}</div>
</div>
<div className = 'flex-basic-container'>
<div className = 'flex-basic-item'>{PlaceHolder}</div>
<div className = 'flex-basic-item'>{PlaceHolder}</div>
<div className = 'flex-basic-item'>{PlaceHolder}</div>
<div className = 'flex-basic-item'>{PlaceHolder}</div>
</div>
<div className = 'flex-basic-container'>
<div className = 'flex-basic-item'>{PlaceHolder}</div>
<div className = 'flex-basic-item'>{PlaceHolder}</div>
<div className = 'flex-basic-item'>{PlaceHolder}</div>
</div>
</div>
css
.placeholder{
background-color : rgb(255, 167, 35);
margin : 10px;
}
.flex-basic-container{
width: 375px;
height:200px;
background-color: bisque;
display:flex;
// 声明主轴为row或者row-reverse,还是column或者column-reverse
flex-direction: row;
// 是否换行,该属性优先级大于子元素的flex属性影响
// 首先会根据flex-basis设置的初始大小计算子元素宽度之和,如果没有flex-basis则根据width属性计算宽度之和
// 如果子元素宽度之和大于父元素宽度则继续下面判断:
// 如果flex-wrap属性为wrap,则会直接换行
// 如果不存在这个属性或者为nowrap,则根据子元素的flex-shrink进行缩放
// 如果子元素宽度之和小于父元素宽度则继续下面判断:
// 如果子元素存在 flex-grow 则按比例分配剩余空间
flex-wrap: wrap;
// 简写 flex-flow: flex-direction flex-wrap
// 则控制主轴上,各个元素的对齐方式
// 如果主轴为row,各列的对齐方式
justify-content: space-between;
// 控制侧轴上,每行(主轴为row)中子元素的横向的对齐方式。
// stretch填充整行,flex-start在父元素的顶部对齐
// align-items: flex-end;
// 控制行与行之间的对齐方式,用于修改flex-wrap属性的行为
// flex-start从父元素的顶部开始挨个向下排列
align-content: center;
.flex-basic-item{
// 如果主轴为row,当父元素宽度大于所有子元素宽度之和,
// flex-grow表示占用剩余宽度的份数,该值设置为0则表示不占用空间
// 如果所有的子元素该属性为0,则都不能放大
flex-grow: 0 ;
// 如果主轴为row,当父元素宽度小于所有子元素宽度之和,则需要减小子元素宽度
// flex-shrink表示需要缩小的宽度占的份数,该值设置为0则表示不能缩小子元素宽度
// 如果所有的子元素该属性为0,则都不能缩小,因此会出现子元素超出父元素
flex-shrink: 1;
// 主轴为row时表示初始宽度,优先级大于width属性
flex-basis: 200px;
width:210px;
// 简写
// flex: flex-grow flex-shrink flex-basis;
// 主轴为row的时候,控制当前子元素在当前行的对齐方式
// 可以通过flex容器的align-items属性来控制每一行中子元素在当前行中的对齐方式
// align-self: flex-start;
background-color: chartreuse;
margin: 5px;
}
}