如何反转包裹上的弹性盒方向以实现“蛇形包裹”?

2024-05-24

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

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 网格解决方案类似于这个 https://stackoverflow.com/a/58598708/8620333它适用于每行固定数量的元素(也称为固定数量的列)。

.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基于每个项目的行位置的属性。我会依靠这个旧答案 https://stackoverflow.com/a/49046973/8620333进行大部分计算以找到行/列数:

//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) to 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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何反转包裹上的弹性盒方向以实现“蛇形包裹”? 的相关文章

  • 更改javascript nodejs中所有页面的href url

    我已经实现了具有多种语言下拉菜单的引导导航栏 当我选择语言时 它将翻译页面 如何更改其他页面的 url 和按钮文本 当我选择french 将所有网址更改为 fr about and fr contact 如何使用 JavaScript 进行
  • 如何保留用户的输入打印?

    我正在尝试添加用户的评论 所以我只是尝试读取输入并将其发送以进行打印 但问题是 一旦我刷新页面或输入另一个输入 打印的输入就会消失 因此 即使刷新页面或重新输入新评论 我也希望始终保持所有用户的显示 代码 div div
  • save_and_open_page 已停止提供我的 CSS

    我的测试设置工作得很好 每当我打电话时 都能提供正确格式的 css 页面save and open page从测试中 然后 我设置了一些 javascript 测试 并对我的设置进行了一些更改 抱歉 我无法详细说明所有内容 我没有足够详细地
  • 如何使自定义 Web 组件可聚焦?

    我正在写一个自定义网络组件 https github com denilsonsa html5 knob这意味着是互动的 我如何告诉浏览器这个自定义组件应该获得焦点 我希望我的自定义元素 可以聚焦 通过选项卡导航 集中注意力时可以接收按键信
  • createHTMLNotification() 替换

    我创建了一个 Chrome 扩展程序 其中使用createHTMLNotification 在所有内容之上显示一个窗口 然而 从 Chrome 28 开始 谷歌决定放弃createHTMLNotification 完全 为什么 谷歌 为什么
  • 在 HTML5 Javascript 中将 BlobBuilder 转换为字符串

    function blobToString blob var reader new FileReader var d reader onloadend function d callback reader result console lo
  • 使用本地存储在从另一个表保存的 HTML TABLE 中打印 JSON,以便我在另一个页面上打印我的表

    在我的作业中 我必须使用用户输入中的数据并将数据保存在本地存储中 我必须以水平表格式将这些数据从本地存储打印到其他页面 为此 我编写了用于用户输入并将数据保存在本地存储中的代码 div p p div
  • 将 XSL-FO 转换为 HTML

    我有一组用于 PDF 生成的 XSL FO 文档 我还需要将相同的输出数据 PDF 格式 导出为 HTML 文件 此外 我需要 HTML 具有与 PDF 类似的样式 有没有办法使用 C 将 XSL FO 转换为 XHTML NOTE 我知道
  • Bootstrap:如何将按钮组对齐在中心(垂直)

    在下面的代码中
  • CSS 继承、别名和其他很酷的东西

    有一天 我随机浏览网页 发现了一些程序 可以让你编写 CSS 别名和其他很酷的东西 我现在不记得了 举个例子 我记得你可以这样做 myclass background color red greenfont 其中 greenfont 在其他
  • 合并 2 个大型 CSS 文件的有效方法

    我正在寻找一个可以合并 2 个大型 CSS 文件的工具 到目前为止我尝试过的所有方法 例如CSSMerge 都没有成功 其中一些只是随机删除属性 其他人则因 webkit 和 moz 等非标准属性而窒息 并给我错误 我还需要保留每条规则大小
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • CSS 到底如何计算相对尺寸

    我想更好地理解某些 CSS 行为 这与具体问题无关 我只是在调试网站时遇到的 让我们在固定位置的 div 中放置一个全宽图像 div img style width 100 src https via placeholder com 150
  • 使用 JavaScript 移动页面上的按钮

    我的按钮可以移动 但奇怪的是 我无法弄清楚偏移是否有问题 我希望我的按钮随着鼠标光标移动 但现在它的移动方式不是我想要的 有时它会消失 另外 创建的新按钮是重叠的 我不知道如何解决这个问题并拥有更好的外观 var coorA var coo
  • 如何始终将焦点保持在文本框中

    我创建了一个包含两个 div 的 HTML 页面 左侧的 div 页面的 90 是 ajax 结果的目标 右侧的 div 页面的 10 包含一个文本框 该页面的想法是在文本框中输入零件编号 通过条形码扫描仪 并显示与该零件编号匹配的绘图 显
  • 具有 100% 高度行和 Internet Explorer 9 的表格

    我有以下示例 div style height 150px background color AAAAFF div
  • 表单发布请求并存储收到的数据

    我有一个非常简单的表单 在提交时发出发布请求
  • 使用 Javascript 设置 cookie [重复]

    这个问题在这里已经有答案了 我正在尝试构建我的第一个移动应用程序 它需要连接到我的 mysql 数据库并使用 json 返回数据 这很好 目前我有一个登录系统 一旦确定用户名和密码存在 它就会返回一条成功消息 对于下一步 我想在我的页面上使
  • 如何从浏览器向服务器发送“页面将关闭”消息?

    我想向每个 html 文档添加一个脚本 JavaScript 该脚本向服务器发送两条消息 页面确实打开了 页面将关闭 此消息包含页面打开的时间 打开消息应在文档加载时 或加载完成时 发送 这是简单的部分 The close message
  • Webpack 4:如何使用 LESS 获取 CSS 源映射?

    多年来我一直在尝试让 CSS 源映射在 webpack 中工作 但没有成功 我不确定链条中哪里出了问题 我希望有人能指出我正确的方向 这是发生的事情 行号是错误的 实际上文件名也是错误的 main less只是包含一堆 import也就是说

随机推荐