Равномерное распределение элементов в блоке (html/css)
У меня есть родительский элемент с фиксированной шириной и высотой. Мне нужно равномерно распределить N дочерних элементов по всей высоте и ширине.
Также нужно учитывать следующие моменты:
- Все дочерние элементы должны иметь одинаковую высоту (не фиксированную);
- Важно: высота и ширина у дочерних элементов имеет соотношение 4 (width) к 3 (height);
- Родительский элемент имеет фиксированную ширину и высоту, то есть не должен иметь скролла даже при сотне дочерних элементов;
Рассмотрим данный пример:
.parent {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
padding: 10px;
gap: 10px;
width: 400px;
height: 150px;
background-color: gray;
}
.child {
flex: 1 1 auto;
width: 100px;
background-color: black;
border: solid 1px white;
}
<div class='parent'>
<div class='child'>beer 1</div>
<div class='child'>beer 2</div>
<div class='child'>beer N</div>
<div class='child'>beer N+1</div>
<div class='child'>beer</div>
</div>
В данном примере все дочерние элементы имеют одинаковую высоту. Нижние элементы имеют разную длину (неприятно, но не критично). Элементы не имеют разрешение 4/3, от которых и должно идти корректное распределение.
Возможно эту задачу можно решить с помощью вычислений в js, но я не придумал хорошей формулы. Также вероятно это возможно с помощью grid, но опять я не смог это сделать.
Ответы (2 шт):
Можно попробовать решить эту задачу с помощью CSS Grid и динамических вычислений, чтобы подстраивать количество колонок и строк в зависимости от количества дочерних элементов
.parent {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(0, 1fr));
justify-content: center;
gap: 10px;
padding: 10px;
width: 400px;
height: 150px;
background-color: gray;
overflow: hidden;
}
.child {
background-color: black;
border: solid 1px white;
aspect-ratio: 4 / 3;
/* Соотношение 4 к 3 */
}
<div class="parent">
<div class="child">beer 1</div>
<div class="child">beer 2</div>
<div class="child">beer N</div>
<div class="child">beer N+1</div>
<div class="child">beer</div>
</div>
Могу предложить такой вариант на flex
:
Родителю задаём:
display: flex; flex-wrap: wrap; justify-content: space-evenly; align-content: space-evenly;
- align-items потому что у нас много строк
- space-evenly т.к. хотим чтобы расстояния были одинаковыми
Дочерним задаём:
min-width: 4px; aspect-ratio: 4 / 3;
- aspect-ratio - по условию
- min-width - чтобы не было слишком мелко
const parent = document.querySelector('div');
const countRange = document.querySelector('input');
const childrenCountDisplay = document.querySelector('span');
const createChild = () => {
const child = document.createElement('div');
child.classList.add('child');
return child;
}
const updateChildren = () => {
const count = Number(countRange.value);
const fragment = document.createDocumentFragment();
childrenCountDisplay.textContent = count;
for (let i = 0; i < count; ++i) {
fragment.append(createChild());
}
parent.innerHTML = '';
parent.append(fragment);
}
updateChildren();
countRange.addEventListener('input', () => updateChildren());
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.parent {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
align-content: space-evenly;
padding: 10px;
gap: 10px;
width: 400px;
height: 150px;
background-color: gray;
}
.child {
min-width: 4px;
aspect-ratio: 4 / 3;
background-color: rgba(0, 0, 0, .5);
outline: solid 1px white;
}
<div class="parent"></div>
<input type="range" min="1" max="200" step="1" value="10" />
<p>Children count: <span>1</span></p>