xxleyi / learning_list

聚集自己的学习笔记
10 stars 3 forks source link

flex 布局之自定义 #266

Open xxleyi opened 3 years ago

xxleyi commented 3 years ago

flex 是一个一维,items 自身可自动伸缩,可调整位置,items 之间剩余空间可分配,同时可以 wrap,可以调整主轴方向和起始方向的布局方案。

这个布局方案由浏览器引擎帮我们实现,提供我们几个可以灵活指定的属性值,友好高效。

比如 justify-content 处理的是主轴上 items 之间的剩余空间如何分配的问题,align-content 处理的是发生 wrap 的情况下,交叉轴上 items 之间的剩余空间如何分配的问题。align-items 处理的是交叉轴上 items 整体位置的问题,align-self 处理的是交叉轴上某个 item 位置的问题。

但是,方案毕竟是方案,肯定有一些 cases 无法被有效覆盖,典型的例子是 just-content 的 space-evenly 至今仍未加入 flex 规范中,但因为使用上相对频繁,各大主流浏览器基本已经实现。

有一些更复杂的情况,可能永远不会被纳入标准,但是顺着 flex 的整体设计思路,开发者完全能够自己实现。

前几天在群里遇到一个小伙伴提出一个布局问题:items 均是定宽定稿元素,容器本身宽度不确定,要求不换行时使用 space-between,换行时之后的元素与之前的元素在交叉轴上保持对齐。

效果如图所示:

image image

如何解决呢?

如何定制呢?就是换行之后,需要针对最后一个 item 设置一个合理的 margin-right 值,这个值可以通过 JS 计算得到。

计算方式如下:

  function onResize() {
    // 假设子元素 width 是 200px,初始 margin 是 10px
    const containerWidth = container.offsetWidth
    const countInOneLine = containerWidth / 220 | 0
    const spaceBetween = containerWidth % 220 / (countInOneLine - 1)
    const totalCount = container.childElementCount
    if (totalCount % countInOneLine) {
      const lastLineCount = totalCount % countInOneLine
      const marginRight = containerWidth - (220 * (lastLineCount) + spaceBetween * (lastLineCount - 1)) + 10
      console.log(marginRight)
      container.lastElementChild.style.marginRight = `${marginRight}px`
    } else {
      console.log('reset')
      container.lastElementChild.style.marginRight = ''
    }
  }