gpt4 book ai didi

html - Flexbox:自动换行方向/ "Snake Wrap"

转载 作者:行者123 更新时间:2023-12-04 12:26:25 26 4
gpt4 key购买 nike

我想找到一种方法,在单个容器中将元素包装到一条与前一行相反的新行中,就像一条蛇自己 flex 一样。我无法使用flexbox以及flex-direction和flex-wrap属性的任何组合来实现此结果。

flexbox结果与期望结果的图像比较:

这是显示flexbox结果与期望结果(伪造)的摘要:

body {
font: 400 14px 'Arial', sans-serif;
}

.title {
font-size: 1em;
padding: 20px 0;
}

.title:first-child {
padding: 0 0 20px;
}

.flex-container, .fake-container, .fake-row {
width: 500px;
background: orange;
display: flex;
}

.flex-container {
flex-flow: row wrap; /* any combination of row/reverse & wrap/reverse */
}

.item {
display: inline-block;
background: purple;
width: 80px;
max-width: 80px;
height: 80px;
margin: 10px;
line-height: 80px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
}

.fake-container {
flex-flow: column nowrap;
}

.fake-row {
flex-flow: row wrap;
height: 100px;
}

.fake-row:nth-child(2) {
flex-flow: row-reverse wrap;
}
<div class="title">Flexbox result:</div>
<div class="flex-container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
</div>

<div class="title">Desired result (faked):</div>
<div class="fake-container">
<div class="fake-row">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
</div>
<div class="fake-row">
<div class="item">6</div>
<div class="item">7</div>
</div>
</div>


尽管我很想找到一个纯CSS解决方案来实现这种“蛇包”,但我开始怀疑它的可能性。我确定可以采用JavaScript解决方案,但不确定如何进行创建而不会使事情过于复杂。

有没有简单的解决方案?感谢您的时间。

最佳答案

CSS网格解决方案similar to this one,每行处理固定数量的元素(也称为固定列数)。

.flex-container {
width: 500px;
background: orange;
display: grid;
grid-template-columns:repeat(5,1fr); /*define the number of column*/
grid-auto-flow:dense; /* this is important to fill all the space*/
grid-gap:20px;
padding:10px;
}

.item {
background: purple;
height: 80px;
line-height: 80px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
}

.item:nth-child(10n + 6) {grid-column:5}
.item:nth-child(10n + 7) {grid-column:4}
.item:nth-child(10n + 8) {grid-column:3}
.item:nth-child(10n + 9) {grid-column:2}
/*.item:nth-child(10n + 10) {grid-column:1} not needed*/
/* For N = number of columns
.item:nth-child((2xN)n + (N+1)) { grid-column:N; }
.item:nth-child((2xN)n + (N+2)) { grid-column:(N-1); }
....
.item:nth-child((2xN)n + (2xN)) { grid-column:1; }

*/

.item:before {
content:counter(num);
counter-increment:num;
}
body {
font: 400 14px 'Arial', sans-serif;
counter-reset:num;
}
<div class="flex-container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>


如果您想要一个通用的解决方案,这里是使用JS和flexbox的解决方案。技巧是根据每个元素的行位置设置 order属性。我将依靠 this old answer进行大部分计算,以便找到行数/列数:

//total number of element
var elems = document.querySelectorAll('.item');
var n_t = elems.length;
//width of an element
var w = parseInt(document.querySelector('.item').offsetWidth);
//full width of element with margin
var m = document.querySelector('.item').currentStyle || window.getComputedStyle(document.querySelector('.item'));
w = w + parseInt(m.marginLeft) + parseInt(m.marginRight);
//width of container
var w_c = parseInt(document.querySelector('.flex-container').offsetWidth);
//padding of container
var c = document.querySelector('.flex-container').currentStyle || window.getComputedStyle(document.querySelector('.flex-container'));
var p_c = parseInt(c.paddingLeft) + parseInt(c.paddingRight);


var adjust = function(){
//only the width of container will change
w_c = parseInt(document.querySelector('.flex-container').offsetWidth);
//Number of columns
nb = Math.min(parseInt((w_c - p_c) / w),n_t);
//Number of rows
nc = Math.ceil(n_t/nb);
for(var j = 0;j<nb;j++) {
for(var i = 0;i<nc;i++) {
if(j + i*nb >= n_t) /* we exit if we reach the number of elements*/
break
if(i%2!=1)
elems[j + i*nb].style.order=j + i*nb; /* normal flow */
else
elems[j + i*nb].style.order=(nb - j) + i*nb; /* opposite flow */
}
}
}

adjust()
window.addEventListener('resize', function(){adjust()})
.flex-container {
background: orange;
display: flex;
flex-wrap:wrap;
}

.item {
background: purple;
height: 80px;
width:80px;
margin:10px;
line-height: 80px;
grid-gap:20px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
}


.item:before {
content:counter(num);
counter-increment:num;
}
body {
font: 400 14px 'Arial', sans-serif;
counter-reset:num;
}
<div class="flex-container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>


在某些情况下,最后一行没有多少内容时,会有一点问题。您可以通过在最后一个元素上添加一些边距来纠正此问题

//total number of element
var elems = document.querySelectorAll('.item');
var n_t = elems.length;
//width of an element
var w = parseInt(document.querySelector('.item').offsetWidth);
//full width of element with margin
var m = document.querySelector('.item').currentStyle || window.getComputedStyle(document.querySelector('.item'));
w = w + parseInt(m.marginLeft) + parseInt(m.marginRight);
//width of container
var w_c = parseInt(document.querySelector('.flex-container').offsetWidth);
//padding of container
var c = document.querySelector('.flex-container').currentStyle || window.getComputedStyle(document.querySelector('.flex-container'));
var p_c = parseInt(c.paddingLeft) + parseInt(c.paddingRight);


var adjust = function(){
//only the width of container will change
w_c = parseInt(document.querySelector('.flex-container').offsetWidth);
//Number of columns
nb = Math.min(parseInt((w_c - p_c) / w),n_t);
//Number of rows
nc = Math.ceil(n_t/nb);
for(var j = 0;j<nb;j++) {
for(var i = 0;i<nc;i++) {
if(j + i*nb >= n_t) /* we exit if we reach the number of elements*/
break
elems[j + i*nb].style.marginLeft='10px'; /*we rest the margin*/
if(i%2!=1)
elems[j + i*nb].style.order=j + i*nb; /* normal flow */
else {
elems[j + i*nb].style.order=(nb - j) + i*nb; /* opposite flow */
/*margin fix*/
if(i == (nc - 1) && (j + i*nb == (n_t - 1)) && j<(nb-1)) {
elems[j + i*nb].style.marginLeft=((nb*nc - n_t)*w + 10) + 'px';
}
}
}
}
}

adjust()
window.addEventListener('resize', function(){adjust()})
.flex-container {
background: orange;
display: flex;
flex-wrap:wrap;
}

.item {
background: purple;
height: 80px;
width:80px;
margin:10px;
line-height: 80px;
grid-gap:20px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
}


.item:before {
content:counter(num);
counter-increment:num;
}
body {
font: 400 14px 'Arial', sans-serif;
counter-reset:num;
}
<div class="flex-container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>



您只需将 if(i%2!=1)更改为 if(i%2!=0),即可轻松切换到其他方向

//total number of element
var elems = document.querySelectorAll('.item');
var n_t = elems.length;
//width of an element
var w = parseInt(document.querySelector('.item').offsetWidth);
//full width of element with margin
var m = document.querySelector('.item').currentStyle || window.getComputedStyle(document.querySelector('.item'));
w = w + parseInt(m.marginLeft) + parseInt(m.marginRight);
//width of container
var w_c = parseInt(document.querySelector('.flex-container').offsetWidth);
//padding of container
var c = document.querySelector('.flex-container').currentStyle || window.getComputedStyle(document.querySelector('.flex-container'));
var p_c = parseInt(c.paddingLeft) + parseInt(c.paddingRight);


var adjust = function(){
//only the width of container will change
w_c = parseInt(document.querySelector('.flex-container').offsetWidth);
//Number of columns
nb = Math.min(parseInt((w_c - p_c) / w),n_t);
//Number of rows
nc = Math.ceil(n_t/nb);
for(var j = 0;j<nb;j++) {
for(var i = 0;i<nc;i++) {
if(j + i*nb >= n_t) /* we exit if we reach the number of elements*/
break
elems[j + i*nb].style.marginLeft='10px'; /*we rest the margin*/
if(i%2!=0)
elems[j + i*nb].style.order=j + i*nb; /* normal flow */
else {
elems[j + i*nb].style.order=(nb - j) + i*nb; /* opposite flow */
/*margin fix*/
if(i == (nc - 1) && (j + i*nb == (n_t - 1)) && j<(nb-1)) {
elems[j + i*nb].style.marginLeft=((nb*nc - n_t)*w + 10) + 'px';
}
}
}
}
}

adjust()
window.addEventListener('resize', function(){adjust()})
.flex-container {
background: orange;
display: flex;
flex-wrap:wrap;
}

.item {
background: purple;
height: 80px;
width:80px;
margin:10px;
line-height: 80px;
grid-gap:20px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
}


.item:before {
content:counter(num);
counter-increment:num;
}
body {
font: 400 14px 'Arial', sans-serif;
counter-reset:num;
}
<div class="flex-container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>

关于html - Flexbox:自动换行方向/ "Snake Wrap",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59481712/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com