如何垂直然后水平包裹一个div

12

我需要在我的网站上水平展示搜索结果数据。我遵循网站的Metro UI设计风格,因此希望数据横向流动而不是纵向。

下图展示了我想要的输出:

Desired OutPut

结果数据是动态的。我想首先根据父级div的高度绘制垂直方向的divs,然后再水平方向上排列,类似于WPF Wrap Panel,但是我尚未实现它。

这是我尝试过的,先水平排列再垂直排列:

Fiddle: http://jsfiddle.net/4wuJz/2/

HTML:

<div id="wrap">
   <div id="wrap1">
       <div class="result">
           <div class="title">1</div>
           <div class="postcontent">  
              <p>Test</p>
           </div>
       </div>

       <div class="result">
           <div class="title">2</div>
           <div class="postcontent">
              <p>Test</p>
           </div>
       </div>
   </div>
</div>

CSS

#wrap {
   width:100%;
   height: 500px;
   background-color: rgba(0,0,0,0.5);
   overflow:scroll;
   overflow-y:hidden;
}

#wrap1 {
   width:2500px;
   height:500px;
   text-align: center;
}


.result {
   width: 300px;
   vertical-align: middle;
   float:left;
   background: rgba(120,30,20,0.5);
   padding: 10px;
   margin: 30px 0px 30px 30px; 
}

我该怎样更改我的代码才能得到所需的输出?是否有任何jQuery插件可以使用?


可能重复问题 http://stackoverflow.com/q/20734869/703717 - Danield
4个回答

7
.result 类添加 clear: left,使你的框垂直堆叠。
然后将结果分组为每3个一组,并将这些分组水平浮动。您可以使用任何后端语言来输出结果标记或使用jQuery进行逻辑操作:
$('.result:nth-child(3n+1)').each(function() {
    $(this).add( $(this).next().next().addBack() ).wrapAll('<div style="float:left"></div>');
});

Fiddle


这里有一个更加响应式的解决方案,可以在窗口大小改变时重新计算:Demo

注意:它假设所有的框都具有相同的高度。如果不是这种情况,您可以在resultHeight变量中硬编码一个max-height

$(window).resize(function() {
    var resultHeight = $('.result:first').outerHeight(true),
        nRows = Math.floor( $('#wrap1').height() / resultHeight );

    $('.results-column').contents().unwrap();
    $('.result:nth-child('+nRows+'n+1)').each(function() {
        $(this).nextAll().slice(0, nRows-1).add(this).wrapAll('<div class="results-column"></div>');
    });
}).resize();

添加了CSS样式:

#wrap1 {
    white-space: nowrap;
}
.results-column {
    display: inline-block;
    vertical-align: top;
}

另外可以看一下Isotope,它具备cellsByColumn/fitColumns布局。


最后,您的用例是使用Flexible Box Layout的典型示例。虽然这种解决方案已经有了其他的答案,但由于目前很难在各个浏览器上实现交叉浏览器的支持,因此我还没有提及它:

  • 火狐 <= 27、IE10 和 Safari <= 6 支持规范的旧版本
  • 更新的 Chrome、Safari 和 IE11 支持新语法
  • 不能忘记所有浏览器前缀!

参考文献:http://caniuse.com/flexbox

但并非一切都已经失去希望。如果您想今天就使用Flexbox,请使用非常有用的Flexbox生成器

使用Flexbox的纯CSS解决方案:演示

#wrap1 {
    display: -webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    -webkit-box-direction: normal;
    -moz-box-direction: normal;
    -webkit-box-orient: vertical;
    -moz-box-orient: vertical;
    -webkit-flex-direction: column;
    -ms-flex-direction: column;
    flex-direction: column;
    -webkit-flex-wrap: wrap;
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
    -webkit-box-pack: start;
    -moz-box-pack: start;
    -webkit-justify-content: flex-start;
    -ms-flex-pack: start;
    justify-content: flex-start;
    -webkit-align-content: flex-start;
    -ms-flex-line-pack: start;
    align-content: flex-start;
    -webkit-box-align: start;
    -moz-box-align: start;
    -webkit-align-items: flex-start;
    -ms-flex-align: start;
    align-items: flex-start;
}

我测试了这个解决方案,在IE10,IE11,Chrome 31,Opera 18和Firefox 29 Nightly中都可以正常工作。
注意:Firefox <= 27不支持具有多行/列的Flexbox(它不支持flex-wrap: wrap)。我在Firefox 29(夜间版)上进行了测试,并且它可以正常工作,因此我相信它很快就会被稳定版本支持。

看起来是一个非常好的方法。我会试一下。唯一的开销是每次调整窗口大小时都需要更改逻辑。 - Monie corleone
你的意思是将垂直方向的盒子数量更改以适应视口吗? - Fabrício Matté
1
@Moniecorleone 更新了。=] 我还没有使用过Isotope,但它似乎可以完全满足你的需求,我也已经将其添加到答案中了。 - Fabrício Matté
非常感谢。我会试一下。 - Monie corleone
1
没问题,为了完整起见,我还添加了一个flexbox的替代方案(需要注意的是它不支持IE<=9,并且在Firefox<=27中由于缺乏wrap支持而存在一些bug)。 - Fabrício Matté
+1 很好的答案 =)平衡的方法来解决 .jsnon-js 的问题,特别是当 flex 填补了其他方案的空白时。 - MackieeE

6

Flexbox将是一种无需JavaScript的解决方案:

#wrap1 {
    display: flex;
    flex-wrap: wrap;
    flex-direction: column;
}

Demo: http://jsfiddle.net/4wuJz/5/


非常有趣 +1,我可以问一下这个在跨浏览器兼容性方面的表现如何吗? - MackieeE
1
Flexbox 让一切变得太容易了。;) 不过需要注意的是要 +1 支持 - Fabrício Matté
1
@MackieeE,请查看Fabricio评论中的链接。尽可能地参考CanIUse,它是网络上最准确和最新的参考资料。 - Pavlo
在Chrome中运行良好。但在Safari和Firefox上不行。虽然我的目标浏览器是Chrome,但我不能使用这种方法,因为将来可能需要支持多个浏览器:( - Monie corleone
Firefox和Safari支持Flexbox,但你需要加入一些前缀以及采用不同的语法。 - Fabrício Matté
我会添加 align-content:start; 来将所有项目堆叠在一起。 - Mark

2

您可以简单地使用CSS列,而不需要改变太多的代码:

div.wrap {
    width: 100%;
    height: 300px;    
    -webkit-column-width: 100px; 
       -moz-column-width: 100px; 
            column-width: 100px;
    -webkit-column-gap: 16px;
       -moz-column-gap: 16px;
            column-gap: 16px;
}

请查看这个代码片段:http://jsfiddle.net/Be9B3/


谢谢,我会试一下。 - Monie corleone

0
你可以使用 display:flex 来实现这个功能。
查看 fork 的 CodePen 演示:http://codepen.io/surjithctly/pen/zolcF 阅读更多 这里HTML
<ul class="flex-container">
  <li class="flex-item">1</li>
  <li class="flex-item">2</li>
  <li class="flex-item">3</li>
  <li class="flex-item">4</li>
  <li class="flex-item">5</li>
  <li class="flex-item">6</li>
</ul>

CSS

.flex-container {
  padding: 0;
  margin: 0;
  list-style: none;
  max-height:600px;
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;

  -webkit-flex-flow: column wrap;
  justify-content: space-around;
}

.flex-item {
  background: tomato;
  padding: 5px;
  width: 200px;
  height: 150px;
  margin-top: 10px;

  line-height: 150px;
  color: white;
  font-weight: bold;
  font-size: 3em;
  text-align: center;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接