flex总结

145 阅读5分钟

flex的布局原理:

  1. 首先根据flex-direction确定主轴以及方向:row、row-reverse、column、column-reverse。以下主轴均为row。
  2. 然后确定flex容器(父元素)的宽度,根据flex项目(子元素)的flex-basis与width(前者优先级大)确定每个flex项目的宽度。
  3. 判断flex容器的宽度与各个flex项目的宽度之和的大小关系:
    • 如果flex容器宽度更大
      1. 如果flex容器的flex-wrap为nowrap
        • 根据每个flex项目的flex-grow按比例来分配剩余的空间
          • 如果flex-grow都为0,则每个flex项目宽度不变,有剩余空间,因此根据flex容器的justify-content在这一行中进行对齐。
          • 如果flex-grow有一个不为0,则剩余空间比分配完。此时flex容器的justify-content则不起作用,因为没有剩余空间进行对齐。
      2. 如果flex容器的flex-wrap为wrap,则flex-wrap没有任何效果,也就不会换行。
    • 如果flex容器宽度更小
      1. 如果flex容器的flex-wrap为nowrap,flex容器的justify-content无效
        • 根据每个flex项目的flex-shrink按比例减小flex项目的宽度。
          • 如果flex-shrink都为0,则每个项目都不会缩小,子元素超出父元素。因此flex容器的justify-content无效。
          • 如果flex-shrink有一个不为0,则按比例缩小相关的flex项目,直到宽度之和与flex容器宽度相等。此时justify-content无效。
  4. 设置单个元素在侧轴的对齐方式:如果flex项目的align-self存在,则根据此属性控制该项目在当前行中的对齐方式,如果不存在align-self属性,则根据flex容器的align-items来控制flex项目的对齐方式,align-items默认为stretch(当项目没有设置高度时,填充整行高度)。
  5. 由于在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;
    }
}