Понятно, что чисто масштабируемого CSS-решения на самом деле не существует для достижения этой цели, поэтому вам понадобится несколько сценариев для динамической настройки некоторых свойств для получения необходимого макета.
Если мы предполагаемчто все элементы имеют одинаковую ширину , мы можем определить количество элементов в строке и применить стили к элементам в зависимости от строки.
Вот базовый пример, основанный на кодеэтот предыдущий ответ: https://stackoverflow.com/a/49046973/8620333
//total number of element
var n_t = $('.item').length;
//full width of element with margin
var w = $('.item').outerWidth(true);
//width of container without padding
var w_c = $('.grid').width();
//nb element per row
var nb = Math.min(parseInt(w_c / w),n_t);
console.log(nb);
$('.item:nth-child(1n+'+(nb+1)+')').addClass('right');
$('.item:nth-child(1n+'+(2*nb+1)+')').removeClass('right');
$('.item:nth-child(1n+'+(3*nb+1)+')').addClass('right');
$('.item:nth-child(1n+'+(4*nb+1)+')').removeClass('right');
window.addEventListener('resize', function(event){
//only the width of container will change
w_c = $('.grid').width();
nb = Math.min(parseInt(w_c / w),n_t);
$('.item').removeClass('right');
$('.item:nth-child(1n+'+(nb+1)+')').addClass('right');
$('.item:nth-child(1n+'+(2*nb+1)+')').removeClass('right');
$('.item:nth-child(1n+'+(3*nb+1)+')').addClass('right');
$('.item:nth-child(1n+'+(4*nb+1)+')').removeClass('right');
});
.grid {
background-color: #ddd;
padding: 10px 0 0 10px;
overflow:hidden;
}
.item {
width: 80px;
height: 80px;
float:left;
clear:right;
background-color: red;
margin: 0 10px 10px 0;
}
.item.right {
float:right;
clear:left;
background:blue;
}
body {
margin:0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="grid">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
<div class="item">F</div>
<div class="item">G</div>
<div class="item">H</div>
<div class="item">I</div>
<div class="item">J</div>
<div class="item">K</div>
<div class="item">L</div>
<div class="item">M</div>
<div class="item">N</div>
<div class="item">O</div>
<div class="item">P</div>
</div>
Этот пример не идеален, поскольку у нас есть проблема с выравниванием, но идея заключается в применении плавающего свойства к строкам путем чередования строк.Я рассмотрел только 4 строки, но мы можем легко сделать его динамическим, используя цикл как показано ниже:
//total number of element
var n_t = $('.item').length;
//full width of element with margin
var w = $('.item').outerWidth(true);
//width of container without padding
var w_c = $('.grid').width();
//nb element per row
var nb = Math.min(parseInt(w_c / w),n_t);
for(var i=1;i<n_t;i++) {
if(i%2==1)
$('.item:nth-child(1n+'+(i*nb+1)+')').addClass('right');
else
$('.item:nth-child(1n+'+(i*nb+1)+')').removeClass('right');
}
window.addEventListener('resize', function(event){
//only the width of container will change
w_c = $('.grid').width();
nb = Math.min(parseInt(w_c / w),n_t);
$('.item').removeClass('right');
for(var i=1;i<n_t;i++) {
if(i%2==1)
$('.item:nth-child(1n+'+(i*nb+1)+')').addClass('right');
else
$('.item:nth-child(1n+'+(i*nb+1)+')').removeClass('right');
}
});
.grid {
background-color: #ddd;
padding: 10px 0 0 10px;
overflow:hidden;
}
.item {
width: 80px;
height: 80px;
float:left;
clear:right;
background-color: red;
margin: 0 10px 10px 0;
}
.item.right {
float:right;
clear:left;
background:blue;
}
body {
margin:0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="grid">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
<div class="item">F</div>
<div class="item">G</div>
<div class="item">H</div>
<div class="item">I</div>
<div class="item">J</div>
<div class="item">K</div>
<div class="item">L</div>
<div class="item">M</div>
<div class="item">N</div>
<div class="item">O</div>
<div class="item">P</div>
</div>
Для лучшего выравнивания мы можем рассмотреть использование CSS-сетки или flexbox, но в этом случае нам нужно будет настроить свойство order объектаэлементы.
С сеткой CSS:
//total number of element
var n_t = $('.item').length;
//full width of element with margin
var w = $('.item').outerWidth(true);
//width of container without padding
var w_c = $('.grid').width();
//nb element per row
var nb = Math.min(parseInt(w_c / w), n_t);
//nb rows
var nr = n_t / nb;
//order of element
var or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
}
}
window.addEventListener('resize', function(event) {
//only the width of container will change
w_c = $('.grid').width();
nb = Math.min(parseInt(w_c / w), n_t);
nr = n_t / nb;
or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
}
}
});
.grid {
background-color: #ddd;
display: grid;
grid-template-columns: repeat( auto-fit, 80px);
padding: 10px 0 0 10px;
}
.item {
height: 80px;
background-color: red;
font-size: 30px;
color: #fff;
font-weight: bold;
margin: 0 10px 10px 0;
}
body {
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="grid">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
<div class="item">F</div>
<div class="item">G</div>
<div class="item">H</div>
<div class="item">I</div>
<div class="item">J</div>
<div class="item">K</div>
<div class="item">L</div>
<div class="item">M</div>
<div class="item">N</div>
<div class="item">O</div>
<div class="item">P</div>
</div>
Этот метод позволяет улучшить выравнивание, но последний ряд не всегда хорош.
Мы можем исправить последнюю строку с помощьюнастройка последних элементов usgin grid-column
как показано ниже:
//total number of element
var n_t = $('.item').length;
//full width of element with margin
var w = $('.item').outerWidth(true);
//width of container without padding
var w_c = $('.grid').width();
//nb element per row
var nb = Math.min(parseInt(w_c / w), n_t);
//nb rows
var nr = Math.ceil(n_t / nb);
//order of element
var or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
/*fix the last row*/
if (i == (nr - 1)) {
$('.item').eq(nb * i + j).css('grid-column', " " + (nb - j));
}
}
}
window.addEventListener('resize', function(event) {
//only the width of container will change
w_c = $('.grid').width();
nb = Math.min(parseInt(w_c / w), n_t);
nr = Math.ceil(n_t / nb);
$('.item').css('grid-column', 'auto');
or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
/*fix the last row*/
if (i == nr - 1) {
$('.item').eq(nb * i + j).css('grid-column', " " + (nb - j));
}
}
}
});
.grid {
background-color: #ddd;
display: grid;
grid-template-columns: repeat( auto-fit, 80px);
grid-auto-flow: dense;
padding: 10px 0 0 10px;
}
.item {
height: 80px;
background-color: red;
font-size: 30px;
color: #fff;
font-weight: bold;
margin: 0 10px 10px 0;
}
body {
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="grid">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
<div class="item">F</div>
<div class="item">G</div>
<div class="item">H</div>
<div class="item">I</div>
<div class="item">J</div>
<div class="item">K</div>
<div class="item">L</div>
<div class="item">M</div>
<div class="item">N</div>
<div class="item">O</div>
<div class="item">P</div>
</div>
Flexbox может быть более подходящим для второго случая (направление столбца).Мы просто делаем то же самое, что ранее рассматривали столбцы вместо строк:
//total number of element
var n_t = $('.item').length;
//full height of element with margin
var w = $('.item').outerHeight(true);
//height of container without padding
var w_c = $('.grid').height();
//nb element per row
var nb = Math.min(parseInt(w_c / w), n_t);
//nb rows
var nr = n_t / nb;
//order of element
var or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
}
}
window.addEventListener('resize', function(event) {
//only the width of container will change
w_c = $('.grid').height();
nb = Math.min(parseInt(w_c / w), n_t);
nr = n_t / nb;
or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
}
}
});
.grid {
display: flex;
height:100vh;
flex-direction:column;
flex-wrap:wrap;
align-items:flex-start;
align-content:flex-start;
padding-top: 10px;
padding-left:10px;
box-sizing:border-box;
}
.item {
height: 80px;
width:80px;
background-color: red;
font-size: 30px;
color: #fff;
font-weight: bold;
margin: 0 10px 10px 0;
}
body {
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="grid">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
<div class="item">F</div>
<div class="item">G</div>
<div class="item">H</div>
<div class="item">I</div>
<div class="item">J</div>
<div class="item">K</div>
<div class="item">L</div>
<div class="item">M</div>
<div class="item">N</div>
<div class="item">O</div>
<div class="item">P</div>
</div>
В некоторых случаях существует также проблема с выравниванием последнего столбца, который мы можем исправить, отрегулировав поле:
//total number of element
var n_t = $('.item').length;
//full height of element with margin
var w = $('.item').outerHeight(true);
//height of container without padding
var w_c = $('.grid').height();
//nb element per row
var nb = Math.min(parseInt(w_c / w), n_t);
//nb rows
var nr = Math.ceil(n_t / nb);
//order of element
var or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else {
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
}
if (i == (nr - 1)) {
/*we add margin+height of non-existing element*/
$('.item:last').css('margin-top', ((nb * nr - n_t) * (80 + 10)) + "px")
}
}
}
window.addEventListener('resize', function(event) {
//only the width of container will change
w_c = $('.grid').height();
nb = Math.min(parseInt(w_c / w), n_t);
nr = Math.ceil(n_t / nb);
or = 0;
$('.item').css('margin-top', 0); /*reset the margin*/
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else {
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
}
if (i == (nr - 1)) {
/*we add margin+height of non-existing element*/
$('.item:last').css('margin-top', ((nb * nr - n_t) * (80 + 10)) + "px")
}
}
}
});
.grid {
display: flex;
height: 100vh;
flex-direction: column;
flex-wrap: wrap;
align-items: flex-start;
align-content: flex-start;
padding-top: 10px;
padding-left: 10px;
box-sizing: border-box;
}
.item {
height: 80px;
width: 80px;
background-color: red;
font-size: 30px;
color: #fff;
font-weight: bold;
margin: 0 10px 10px 0;
}
body {
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="grid">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
<div class="item">F</div>
<div class="item">G</div>
<div class="item">H</div>
<div class="item">I</div>
<div class="item">J</div>
<div class="item">K</div>
<div class="item">L</div>
<div class="item">M</div>
<div class="item">N</div>
<div class="item">O</div>
<div class="item">P</div>
</div>