我想布局类似于 this:
的 unicode 字形显示的集合中可能有 13 到 100 个项目(字母表、辅音字母、附音表、音节文字等),因此可能有一组包含 99 个项目的集合,或者一组包含 16 个项目的集合,等等。
如何才能最漂亮(并且自动)布局元素(以便响应时也很好)?这是我默认使用 Flexbox 的内容:
每个项目都有固定的高度,宽度是响应式的(但每个元素都相同)。
目标是让每一行都有偶数或奇数个项目。这样,所有垂直列都会对齐(并且它不会像我的动画 gif 那样,偶数/奇数行混合在一起)。
你会怎么做?
我有一个 React 组件,它的 Flexbox 布局类似于
<Grid minWidth={96} gap={8} maxColumns={5} breakpoints={[5, 3, 1]} />
,其中 breakpoints
是每行允许的项目数,maxColumns
是最大列数 (断点/maxColumn 有点多余,你可以定义或者,也许我稍后会清理它)。所有这些信息可能无关紧要,但只是指出以防万一,这是我的响应式网格组件。
我怎样才能以某种方式将我的总数除以x以确定它应该是偶数行还是奇数行,然后将
maxColumns
或breakpoints
设置为“最紧凑”的值?例如:
它的“美”可能是主观的,并没有明确的规则来定义什么是最美的。只是寻找任何不容易在末尾留下孤立的单个节点,然后在所有其他行上有 7 个项目的东西。理想情况下我们有:
maxRowCount - 2
(因此,如果所有行都有 7,则最后一行只能有 5 或 7,或者如果所有行都有 5,则最后一行行只能有 3 或 5 等)。minWidth: 96px
,并且会增长以填充空间。一旦我们掌握了这项工作的基础知识,我就可以弄清楚如何让事情做出响应,但假设存在 containerWidth
。所以在我的脑海里,说我们有
containerWidth === 700px
。然后,700/96 == 7+
,所以每行可能有 7 个。例如,如果我们有 99 个项目,则 99 % 7 == 1
,因此 7
不起作用,因为最后一行有 1 个项目。 6
不起作用,因为 99
是偶数,所以尝试 5
? 99 % 5 == 4
,这是行不通的,因为 4
是偶数。所以尝试一下3
,99 % 3 == 0
,这样就可以按原样工作,使用它!
你会如何实现这样的事情?
这样的事情看起来是正确的,但是我正确解决了吗?
console.log(
99,
calculateColumns({ totalCount: 99, itemWidth: 96, containerWidth: 700 })
);
console.log(
98,
calculateColumns({ totalCount: 98, itemWidth: 96, containerWidth: 700 })
);
console.log(
97,
calculateColumns({ totalCount: 97, itemWidth: 96, containerWidth: 700 })
);
console.log(
96,
calculateColumns({ totalCount: 96, itemWidth: 96, containerWidth: 700 })
);
console.log(
95,
calculateColumns({ totalCount: 95, itemWidth: 96, containerWidth: 700 })
);
console.log(
94,
calculateColumns({ totalCount: 94, itemWidth: 96, containerWidth: 700 })
);
console.log(
93,
calculateColumns({ totalCount: 93, itemWidth: 96, containerWidth: 700 })
);
function calculateColumns({ totalCount, itemWidth, containerWidth }) {
let max = Math.min(Math.floor(containerWidth / itemWidth), 7)
while (max > 3) {
const maxIsEven = isEven(max)
const remainder = totalCount % max
const remainderIsEven = isEven(remainder)
if (maxIsEven && remainderIsEven) {
const diff = max - remainder
if (diff <= 2) {
return max
}
} else if (!maxIsEven && (!remainderIsEven || !remainder)) {
const diff = max - remainder
if (diff <= 2) {
return max;
}
} else {
// one is even, one is odd
}
max--
}
return max
}
function isEven(n) {
return n % 2 === 0
}