function getBestItemBounds(config) {
const actualRatio = config.width / config.height
console.log(actualRatio)
let best
console.log(config.aspectRatio)
for (let rowCount = 1; rowCount <= config.maxRows; rowCount++) {
if (rowCount > config.itemCount) continue
const colCount = Math.ceil(config.itemCount / rowCount)
const ratio = (config.aspectRatio * colCount) / rowCount
let itemHeight;
let itemWidth;
if (ratio < actualRatio) {
itemHeight = (config.height - (config.minGap * rowCount)) / rowCount
itemWidth = itemHeight * config.aspectRatio
} else {
itemWidth = (config.width - (config.minGap * colCount)) / colCount
itemHeight = itemWidth / config.aspectRatio
}
var totalItemArea = config.itemCount * itemHeight * itemWidth
var diff = (config.width * config.height) - totalItemArea
if (!best || diff < best.diff) {
best = { itemWidth, itemHeight, ratio, diff }
}
}
const result = { itemWidth: best.itemWidth, itemHeight: best.itemHeight }
console.log(result)
return result
}
function resetContainerItems() {
const itemCount = document.querySelectorAll('.item').length
if (!itemCount) return
const container = document.getElementById('container')
const rect = container.getBoundingClientRect()
const { rowCount, colCount, itemWidth, itemHeight } = getBestItemBounds({
width: rect.width,
height: rect.height,
itemCount,
aspectRatio: 16 / 9,
maxRows: 10,
minGap: 5
})
container.style.setProperty('--item-width', itemWidth + 'px')
container.style.setProperty('--item-height', itemHeight + 'px')
}
const resObs = new ResizeObserver(() => resetContainerItems())
resObs.observe(document.getElementById('container'))
let counter = 0
document.getElementById('add').onclick = () => {
const elem = document.createElement('div')
elem.className = 'item'
const button = document.createElement('button')
button.innerText = 'Delete Item #' + (++counter)
button.onclick = () => {
document.getElementById('container').removeChild(elem)
resetContainerItems()
}
elem.appendChild(button)
document.getElementById('container').appendChild(elem)
resetContainerItems()
}
#container {
display: inline-grid;
grid-template-columns: repeat(auto-fit, var(--item-width));
grid-template-rows: repeat(auto-fit, var(--item-height));
place-content: space-evenly;
width: 90vw;
height: 90vh;
background-color: green;
}
.item {
background-color: blue;
display: flex;
align-items: center;
justify-content: center;
}
<button id="add">Add Item</button><br />
<div id="container"></div>