//total number of elementvar elems = document.querySelectorAll('.item');var n_t = elems.length;//width of an elementvar w = parseInt(document.querySelector('.item').offsetWidth);//full width of element with marginvar m = document.querySelector('.item').currentStyle || window.getComputedStyle(document.querySelector('.item'));w = w + parseInt(m.marginLeft) + parseInt(m.marginRight);//width of containervar w_c = parseInt(document.querySelector('.flex-container').offsetWidth);//padding of containervar 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 elementvar elems = document.querySelectorAll('.item');var n_t = elems.length;//width of an elementvar w = parseInt(document.querySelector('.item').offsetWidth);//full width of element with marginvar m = document.querySelector('.item').currentStyle || window.getComputedStyle(document.querySelector('.item'));w = w + parseInt(m.marginLeft) + parseInt(m.marginRight);//width of containervar w_c = parseInt(document.querySelector('.flex-container').offsetWidth);//padding of containervar 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 elementvar elems = document.querySelectorAll('.item');var n_t = elems.length;//width of an elementvar w = parseInt(document.querySelector('.item').offsetWidth);//full width of element with marginvar m = document.querySelector('.item').currentStyle || window.getComputedStyle(document.querySelector('.item'));w = w + parseInt(m.marginLeft) + parseInt(m.marginRight);//width of containervar w_c = parseInt(document.querySelector('.flex-container').offsetWidth);//padding of containervar 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>I would like to find a way to have elements in a single container wrap to a new line going the opposite direction of the previous line, like a snake curving back on itself. I have not been able to achieve this result with flexbox and any combination of flex-direction and flex-wrap properties.Image comparison of flexbox result vs desired result:And here is a snippet showing the flexbox result vs desired result (faked):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>As much as I would love to find a pure CSS solution to achieve this "snake wrap", I am starting to doubt its possibility. I'm sure a javascript solution could be employed, but am unsure how to proceed in creating one without making things overly-complicated.Is there any simple solution out there? Thank you for your time. 解决方案 A CSS grid solution similar to this one that works with a fixed number of elements per row (aka fixed number of columns)..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>If you want a generic solution here is one using JS and flexbox. The trick is to set the order property based on the row position of each item. I will rely on this old answer to do most of the calculation in order to find the number of rows/columns://total number of elementvar elems = document.querySelectorAll('.item');var n_t = elems.length;//width of an elementvar w = parseInt(document.querySelector('.item').offsetWidth);//full width of element with marginvar m = document.querySelector('.item').currentStyle || window.getComputedStyle(document.querySelector('.item'));w = w + parseInt(m.marginLeft) + parseInt(m.marginRight);//width of containervar w_c = parseInt(document.querySelector('.flex-container').offsetWidth);//padding of containervar 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>There is a little issue with the last line in some cases when it's not full of item. You can rectify this by adding some margin to the last element//total number of elementvar elems = document.querySelectorAll('.item');var n_t = elems.length;//width of an elementvar w = parseInt(document.querySelector('.item').offsetWidth);//full width of element with marginvar m = document.querySelector('.item').currentStyle || window.getComputedStyle(document.querySelector('.item'));w = w + parseInt(m.marginLeft) + parseInt(m.marginRight);//width of containervar w_c = parseInt(document.querySelector('.flex-container').offsetWidth);//padding of containervar 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>You can easily switch to the other direction by simply changing if(i%2!=1) to if(i%2!=0)//total number of elementvar elems = document.querySelectorAll('.item');var n_t = elems.length;//width of an elementvar w = parseInt(document.querySelector('.item').offsetWidth);//full width of element with marginvar m = document.querySelector('.item').currentStyle || window.getComputedStyle(document.querySelector('.item'));w = w + parseInt(m.marginLeft) + parseInt(m.marginRight);//width of containervar w_c = parseInt(document.querySelector('.flex-container').offsetWidth);//padding of containervar 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> 这篇关于Flexbox:包装纸上的反方向/“蛇皮纸"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-29 07:12