CSS3中平衡的交替列布局

时间:2013-07-11 15:49:57

标签: css css3

我正在尝试创建一个平衡的(2-)列布局。

内容不是文本,而是块,高度不同。 只要“左”和“右”具有(大致)相同的高度,内容应交替左右放置。

即。在这张图片中: enter image description here 1到3之间的空间不应该存在。

或者在此图片中: enter image description here 2'应该独立在右侧,1,3和4应该站在左侧(它们之间没有空间)。

我尝试使用“浮动<li>”,就像这样:

HTML:

<ol class="context">
    <li class="gruppe">1</li>
    <li class="gruppe">2.0<br />2.1</li>
    <li class="gruppe">3.0<br />3.1</li>    
    <li class="gruppe">4</li>
</ol>

CSS:

ol.context 
{
  border: 1px solid #048;
  list-style: none;
  margin: 0;
  padding: 0 0 8px 0;
  overflow: auto;
}

li.gruppe
{
  background: #048;
  color: white;
  float: left;
  font: bold 32px Arial, sans-serif;
  margin: 1px;
  text-align: center;
  width: calc(50% - 2px);
}

(请参阅attempt 1attempt 2

我还尝试使用列(column-count: 2; column-fill: auto;),但这并不是从左到右填充列。 (它首先从上到下填充。)

如果没有JavaScript,这甚至可以吗?

6 个答案:

答案 0 :(得分:5)

我想说如果没有JS,这是不可能的。这是我根据Ben Holland的一篇文章制作的小提琴。至少在我身上看起来像你在追求的。

http://jsfiddle.net/QWsBJ/2/

HTML:

<body onload="setupBlocks();">
  <div class="block">
    <p>***Content***</p>
  </div>
  <div class="block">
    <p>***Content***</p>
  </div>
  <div class="block">
    <p>***Content***</p>
  </div>
  <div class="block">
    <p>***Content***</p>
  </div>
  <div class="block">
    <p>***Content***</p>
  </div>
</body>

CSS:

.block {
  position: absolute;
  background: #eee;
  padding: 20px;
  width: 300px;
  border: 1px solid #ddd;
}

JS:

var colCount = 0;
var colWidth = 0;
var margin = 20;
var blocks = [];

$(function(){
    $(window).resize(setupBlocks);
});

function setupBlocks() {
    colWidth = $('.block').outerWidth();
    colCount = 2
    for(var i=0;i<colCount;i++){
        blocks.push(margin);
    }
    positionBlocks();
}

function positionBlocks() {
    $('.block').each(function(){
        var min = Array.min(blocks);
        var index = $.inArray(min, blocks);
        var leftPos = margin+(index*(colWidth+margin));
        $(this).css({
            'left':leftPos+'px',
            'top':min+'px'
        });
        blocks[index] = min+$(this).outerHeight()+margin;
    }); 
}

Array.min = function(array) {
    return Math.min.apply(Math, array);
};

答案 1 :(得分:2)

更新:我认为仅使用CSS几乎不可能实现这一点。有许多不同的解决方案,但除非您愿意使用JavaScript或某些服务器端代码,否则它们都需要一些妥协。

使用CSS列

这是使用重新排序的块的an alternate fiddle。这是使用CSS列的fiddle demo,无需重新排序。

您可以使用 CSS colunms 将块流量更改为垂直,除非您更改其输出顺序。如果你可以先输出奇数,那么偶数,你就赢了。

<div class="wrapper">
  <div class="block1">1</div>
  <div class="block3">3</div>
  <div class="block2">2</div>
  <div class="block6">4</div>
</div>

.wrapper {
    column-count: 2;
    column-width: 100px;
    -moz-column-width: 100px;
    -webkit-column-width: 100px;
    width: 260px;
}
div {
    border: 1px solid #999;
    display: inline-block;
    margin: 10px;
    width: 100px;
}
.block1 { height: 100px; }
.block2 { height: 130px; }
.block3 { height: 150px; }
.block4 { height: 100px; }

此解决方案与IE9及以下版本不兼容。

块高度已知

如果您确实知道了块高,可以使用绝对定位解决此问题。

block1 {
  height: 100px;
  position: absolute;
  left: 0; 
  top: 0;
}

block2 {
  height: 110px;
  position: absolute;
  left: 0; 
  top: 100px; /* The height of the div above it */
}

一个很大的缺点是动态内容;我们很少知道块高度。因此,除非您愿意计算高度块高度,否则此解决方案的应用非常有限。

如果您愿意使用JS

使用像Masonry这样的插件。这两者都在vanilla jsjQuery flavour

其他选项

这将为您提供以下需要妥协的选项。

  1. 将您的块分组为列。见this Fiddle for a demo。这会将块的流量改变为垂直,然后是水平。

  2. 在您的街区上使用display: inline-block; vertical-align: top;。这将在块下面留下一些空白区域。

  3. 强制阻止块的高度,使其成为非问题。对于具有其他内容的块,请使用overflow属性以允许块内滚动。

  4. 正如其他人所评论的那样,您可以尝试计算服务器上块的高度。

答案 2 :(得分:0)

你可以尝试混合使用flex和float(仅在Firefox / IE10和safari 5.1.7中测试,因为我个人认为,CSS不是你的解决方案)

http://codepen.io/gcyrillus/pen/zgAiw

但是,在您选择的任何CSS情况下,最好是继续使用mansonry脚本。 CSS并没有真正适应这种布局。此时你有很多CSS方法用于布局和基本:display和float。

您可以在html树结构中轻松地使用它,但这种方法并不是混合使用。 boxe将是浮动的,内联级别框或块级别框,并且每个都假设在流中进行交互。 浮动,在非浮动元素之后打破一条线或向下滑动直到它有足够的空间,你通过CSS r右/左派遣。

内联块远离浮动元素并在没有足够空间的情况下断开一条线,内联块之间的浮动元素将在浮动之前保持断行。

列CSS将逐个填充内容列。见:http://codepen.io/gcyrillus/pen/AtazJ

Inline-flex元素似乎适用于浮动元素......但它是否假设它是一个经过验证的规则?

似乎对我有用的是,使用javascript进行预期的布局并在float或display上继续:inline-block + width作为后退。

最后的解决方案是在您的服务器端提前考虑这一点,并在2个容器中使用另一个适当的标记发送您的项目(如果可能的话)(不知道您的ol li中发送的真实内容)。

FLEX测试的CSS:

li.gruppe
{
  background: #048;
  color: white;
  font: bold 32px Arial, sans-serif;
  text-align: center;
  box-sizing:border-box;
  border-bottom:1px solid white;
   border-bottom:1px solid white;
    display: -webkit-inline-flex;
  display: -moz-inline-flex;
  display: -ms-inline-flex;
  display: inline-flex;  
  width:50%;
 }
li:nth-child(even){
  float:right;
  clear:right;
  border-left:1px solid white;
  margin-top:0;
}

答案 3 :(得分:0)

编辑:这是一个有趣的解决方案,但不幸的是,它不能解决所要求的问题。

我在此提出的解决方案将后续元素放在交替的列中,因此:1->左,2->右,3->左,4->右,等等。

这本身就是一个有趣的问题,但不是要求的。

感谢@Nils指出这一点。

原始答案

这是我用flex的尝试!
https://jsfiddle.net/vqLr8t3e/

我不确定它是否可以在IE11中使用。

代码

.the-beginning {
  background: green;
  color: white;
  font-weight: bold;
  text-align: center;
  cursor: pointer;
}

.the-end {
  background: red;
  color: white;
  font-weight: bold;
  text-align: center;
  cursor: pointer;
}

.container-outer {
  overflow: hidden;
}

.container {
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
  max-height: 19999px;
  margin-top: -10000px;
}

.container > div {
  width: 50%;
  box-sizing: border-box;
  border: 5px solid grey;
  padding: 5px;
  background: white;
  order: 1;
}

.container > div:nth-child(odd) {
  order: -1;
}

.container > div:nth-child(1),
.container > div:nth-child(2) {
  margin-top: 10000px;
}
<div class="the-beginning">THE BEGINNING</div>
<div class="container-outer">
  <div class="container">
    <div>LEFT 0</div>
    <div>RIGHT 0<br>RIGHT 0</div>
    <div>LEFT 1<br>LEFT 1<br>LEFT 1</div>
    <div>RIGHT 1</div>
    <div>LEFT 2</div>
    <div>RIGHT 2<br>RIGHT 2<br>RIGHT 2</div>
  </div>
</div>
<div class="the-end">THE END</div>

想法

第一步是在容器上使用flex-direction: column;flex-wrap: wrap;,在项目上使用width: 50%;,作为在列中显示项目的第一步。

使用order: -1;order: 1将奇数和偶数元素排序到不同的列中。

在每列的第一个元素上使用免费margin-top: 10000px;,在容器上使用max-height: 19999px;,这样一列中就不会有两个这样的项目。这将确保所有这些项目都在新列中开始。用容器上的负边距补偿。用带有overflow: hidden;的外部容器将其切断。

答案 4 :(得分:-2)

我不确定我是否做对了。 。

  

“2'应该独立于右侧,1,3和4   应该站在左侧(它们之间没有空间)。“

<强> HTML:

<div id="box">
    <div class="data">1</div>
    <div class="data" style="float:right">2<br/>2<br/>2<br/>2</div>
    <div class="data">3<br/>3</div>
    <div class="data">4</div>
</div>

<强>的CSS:

#box {
    width:100%;
    height:auto;
    float:left;
}
.data {
    height:auto;
    width:50%;
    float:left;
    background-color:#ccc;
    border-bottom:solid 1px #000;
}

Fid的: http://jsfiddle.net/YdEW9/26/

这是纯粹的CSS。一切都是floated left然后使用float:right

给div上的(4) 2's带内联css

我有点不知道如何在没有javascript的情况下设置inline-css。服务器端可能吗?但我怀疑你能否获得元素的高度。

好吧无论如何希望这会有所帮助。

答案 5 :(得分:-2)

PURE CSS SOLUTION:

将以下内容添加到您的css文件中:

ol.context li:nth-child(even) {
float: right;
}

请勿更改您的HTML或其他任何内容。

FF中的结果:

Firefox rendering

-

如何运作

我们不是将所有元素“左”浮动并创建间隙,而是根据它们所在元素的边/列浮动每个容器。