两端对齐图片墙:让 flex-grow 正比于 flex-basis
相册 / 画廊版式要的是:同一行图片等高、各图宽度随自身宽高比、整行两端撑满(Google 图片、Flickr 都这么排)。这页把它落到 flex-grow 与
flex-basis 上:只要令每个 item 的 flex-basis 与 flex-grow 同时等于「该图缩到统一高度时的宽度」,整行就退化成等比缩放——行内自动等高、自动撑满。拖容器宽与基准行高,用 getBoundingClientRect
实测每行高度验证。
一句话的配方。 设基准行高 H,每张图归一化到该高度时的宽度为
。把它同时写进两处:flex-basis: wᵢ 定起点、flex-grow: wᵢ 定瓜分权重。再开 flex-wrap: wrap 让放不下时换行。下面切到「等比撑满」模式即是此配方。
1 · 拖参数,逐行实测「行内是否等高」
每张都是真实图片(尺寸各异),左下角标 flex-grow / flex-basis 的取值(两者相等)、右上角是 getBoundingClientRect 实测高度。切到「原始宽 +
wrap」可见每行右侧参差留白;切到「等比撑满」则两端对齐、且同一行各图高度一致。末行单独描白边——它正是需要特殊处理的那一行。
为什么行内会精确等高。 接 分配公式 代入
:。系数 k 对同一行所有 item 相同,于是每块宽度都乘同一个 k、高度
也随之一致——整行等价于等比缩放。这正是「让 flex-grow 正比于 flex-basis」的意义:把剩余空间按起点尺寸的比例分回去,形状不变、只是放大。
2 · 末行为什么要单独处理
末行 item 少、free 大,同样乘以 k 会比其他行明显高出一截。给容器加一个隐形伪元素 ::after { content: ''; flex-grow: 99999 }:它的 grow 权重远超所有 item 之和,几乎把末行的剩余空间全部吃掉,于是末行各图的
、维持基准高 H 并靠左排列。把上面「末行处理」切到「不处理」,即可看到末行被异常放大。
这是 CSS 方案的取舍。 flex 版把「分配」整件事交给浏览器,代码近乎为零、天生响应式,代价是末行只能靠 ::after 这类 trick 收尾、且无法精确指定每行行高。要精确控制(每行二分出一个行高使总宽恰等于容器宽、单独决定末行是否撑满),就回到 JS 方案:逐行
二分行高 + 绝对定位摆放,精确但需脚本与 resize 重算。
| CSS Flex(本页) | JS 二分 + 绝对定位 | |
|---|---|---|
| 代码量 | 近乎为零(两行声明) | 需布局算法 + resize 监听 |
| 响应式 | 天然(浏览器重排) | 手动重算 |
| 行高精度 | 浏览器按 k 缩放,不指定具体行高 |
二分到任意精度 |
| 末行 | 靠 ::after trick 收尾 |
可任意决定撑满 / 靠左 |
| 间距 | gap 先扣除再分配(见 gap 页) |
自行在坐标里留出 |