如何在布局中始终平均分配剩余空间给间隙(gap)

不废话,直接上代码:

import { useEffect } from "react";
import "./styles.css";

export default function App() {
  function dynamicCalculate() {
    const container = document.getElementById("container") as HTMLElement;
    const item = container.firstElementChild as HTMLElement;

    let W: number; // Width of container.
    let w: number; // Width of item.
    let b: number; // Border's width of item.
    let minGap: number; // Minimum gap between items.
    let gap: number; // Gap between items.
    let n: number; // Number of items in one row.

    W = container.clientWidth;
    w = item.clientWidth;
    b = +window.getComputedStyle(item).borderWidth.replace("px", "") * 2;
    w = w + b;
    minGap = 16;
    n = Math.floor(W / w);

    function calc(n: number): [number, number] {
      gap = (W - n * w) / (n + 1);
      if (gap < minGap) {
        n--;
        gap = (W - n * w) / (n + 1);
        return calc(n);
      }
      return [n, gap];
    }
    [n, gap] = calc(n);
    console.log(`Put ${n} items in one row, gap is ${gap}px.`);
    const halfGap = gap / 2;
    container.style.paddingLeft = `${halfGap}px`;
    container.style.paddingRight = `${halfGap}px`;
    for (let item of container.children) {
      (item as HTMLElement).style.marginLeft = `${halfGap}px`;
      (item as HTMLElement).style.marginRight = `${halfGap}px`;
    }
  }

  useEffect(() => {
    dynamicCalculate();
    window.addEventListener("resize", dynamicCalculate);
    return () => {
      window.removeEventListener("resize", dynamicCalculate);
    };
  }, []);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      {/* demo */}
      <div
        id="container"
        className="flex-h wrap"
        style={{
          display: "flex",
          flexFlow: "row wrap",
          border: "1px solid red"
        }}
      >
        {Array.from({ length: 20 }).map((v, i) => {
          return (
            <div
              className="flex-h center"
              style={{
                display: "flex",
                justifyContent: "center",
                alignItems: "center",
                border: "1px solid blue",
                width: "100px",
                height: "120px"
              }}
            >
              Item-{i}
            </div>
          );
        })}
      </div>
    </div>
  );
}

codesandbox地址demo在线预览

03-05 16:59