六维教程

CSS Flex 项目属性

项目属性管弹性

容器属性管整体布局,这一篇讲写在项目上的属性。它们解决同一类问题,项目怎么瓜分空间、怎么排序、怎么单独对齐。核心有三个,flex-grow、flex-shrink、flex-basis,后面跟着两个小帮手,align-self 和 order。

flex-grow,放大瓜分剩余空间

flex-grow 管的是容器有剩余空间时,项目按什么比例放大。默认值是 0,意思是即使有剩余空间,项目也不放大。

三个项目 flex-grow 分别是 1、1、2,剩余空间会被分成四份,前两个各拿一份,最后一个拿两份。数字不必是整数,0.5 也可以。

注意 flex-grow 分配的是剩余空间,不是整个宽度,项目原本的内容宽度不会被重新分配。三个项目全写 0,剩余空间就空着,谁都不拿。

flex-shrink,缩小应对空间不足

flex-shrink 和 flex-grow 相反,空间不够时按比例缩小。默认值是 1,所以上一篇说的压缩行为,其实是默认值造成的。

把某个项目设成 0,它在空间不足时也不会被压缩,宁可撑破容器也不牺牲自己。

典型场景是带 logo 的导航,logo 被压扁很难看,让它固定不动,让其他链接去承担缩小。

flex-basis,基准尺寸

flex-basis 定义项目在放大和缩小之前的基准尺寸。默认值 auto,意思是优先用 width 的值,没写 width 就用内容宽度。

给 flex-basis 设一个具体的像素值或百分比,相当于给它一个虚拟的初始宽度,之后的放大缩小都基于这个值。

三个属性分开讲完了,放在一个例子里对比更直观。

.item-a {
  flex-grow: 1;   /* 剩余空间拿 1 份 */
}

.item-b {
  flex-grow: 1;   /* 剩余空间拿 1 份 */
}

.item-c {
  flex-grow: 2;   /* 剩余空间拿 2 份 */
}

.item-logo {
  flex-shrink: 0;   /* logo 永远不缩小 */
}

.sidebar {
  flex-basis: 200px;   /* 基准 200px,放得下就不变 */
}

和 width 的区别在于,flex-basis 会参与弹性计算。空间充足时项目可以长得比基准大,空间不足时可以缩得比基准小,width 是死值,不参与这套弹性逻辑。

flex 简写

三个属性分开写太啰嗦,实际开发几乎都用简写 flex。三个常用组合必须背下来。

简写 展开 记忆点
flex: 1 flex-grow 1,flex-shrink 1,flex-basis 0% 均分剩余空间
flex: auto flex-grow 1,flex-shrink 1,flex-basis auto 按内容自适应
flex: none flex-grow 0,flex-shrink 0,flex-basis auto 尺寸固定不变

flex: 1 最常用,三个项目都写 flex: 1,剩余空间均分,效果等同均分整行。flex: auto 在空间不足时会被压缩,flex: none 则完全拒绝变化,适合头像、图标这类固定元素。

记忆口诀,none 拒绝变化,1 全都要,auto 看内容。

.item {
  flex: 1;        /* 等价于 flex: 1 1 0%,均分剩余空间 */
}

.fixed {
  flex: none;     /* 等价于 flex: 0 0 auto,尺寸固定 */
}

align-self,单独对齐

align-self 允许单个项目脱离容器的 align-items 规则,自己定交叉轴对齐方式。默认值 auto,意思是继承容器的设置。

.toolbar {
  display: flex;
  align-items: center;     /* 默认都居中 */
}

.toolbar .icon {
  align-self: flex-start;  /* 这个图标顶到上方 */
}

常见场景是混排,大部分项目垂直居中,唯独某个图标要对齐顶部,写 align-self 一次搞定,不用为它单独包一层容器。

order,调整视觉顺序

order 调整项目的显示顺序,默认值 0,数值小的排前面,负数排得更靠前。它只改变视觉顺序,DOM 顺序不变。

屏幕阅读器按 DOM 顺序朗读,所以 order 重排后的页面,读出来的顺序是乱的。能用 DOM 顺序解决就别用 order,实在要用也要确认无障碍场景可接受。

经典导航栏示例

把上面所有属性串起来,做一个经典导航栏,logo 在左,链接居中,按钮在右。

<nav class="navbar">
  <a href="#" class="logo">Logo</a>
  <ul class="links">
    <li><a href="#">首页</a></li>
    <li><a href="#">教程</a></li>
    <li><a href="#">关于</a></li>
  </ul>
  <a href="#" class="btn">登录</a>
</nav>
.navbar {
  display: flex;
  align-items: center;      /* 三块内容垂直居中 */
}

.links {
  display: flex;
  flex: 1;                  /* 链接区吃掉中间所有空间 */
  justify-content: center;  /* 链接在中间区域里居中 */
}

.btn {
  flex: none;               /* 按钮尺寸保持原样 */
}

链接区 flex: 1 吃掉剩余空间,把 logo 顶到左端,把按钮顶到右端,链接自己再居中,一个布局三行代码搞定。这里用到的 CSS 属性关键字其实都学过了,auto 和 0 的含义,和别处一模一样。

小结

flex-grow 管放大,flex-shrink 管缩小,flex-basis 管基准,三个配合的简写记住 flex: 1、flex: auto、flex: none 就够了。align-self 负责单兵作战,order 负责悄悄换位。下一篇进入实战,把这四篇的知识用在真实布局里。

上一篇
CSS Flex 容器属性
下一篇
CSS Flexbox 实战