没有包装器,是否可以任意向左或向右堆叠无限的div?

时间:2014-11-18 01:34:31

标签: html css

我认为这会(相对)容易,但从答案来看,它似乎比我预期的更难。

也许甚至不可能!

目标

我想要一个可以任意分配.left.right类的div元素列表。

所有.left div应该在左侧彼此叠加,.right div应该在右侧相互叠加。每个类中的div数是任意的。

enter image description here

三个条件

  1. 每个div的高度不会提前知道

  2. 我希望他们在指定的对方下面叠加 一边,无论有多少div,它们出现的顺序,以及有多少 分配到任何一方

  3. 我不想使用'包装'一些人建议的div。这是 因为解决方案必须满足随机数量和排序 .left.right div(参见下面的示例)。

  4. 理想情况下,我希望它是一个纯粹的html / css解决方案,尽可能向后兼容 - 尽管我意识到这可能是不切实际的。

    示例HTML

    <div class="left">left one</div>
    <div class="left">left two</div>
    <div class="right">right one</div>
    <div class="left">left three</div>
    <div class="right">right two</div>
    <div class="right">right three</div>
    <div class="left">left four</div>
    <div class="right">right four</div>
    <div class="right">right five</div>
    <div class="left">left five</div>
    <div class="right">right six</div>
    <div class="right">right seven</div>
    

    更新

    经过这么多答案,我对答案/技巧的范围印象深刻,但没有一个能完全满足所有条件。

    因此,我试图找到一个可靠的解决方案,在我微薄的声誉中占了四分之一!

    更新2

    我的原始目标似乎是可以撤销的。所以我没有给出任何答案,虽然我已经把它给了Josh,但是给了我(几乎)实现这个目标的最佳方式,以及对他使用的css的很好的解释。

    感谢大家的帮助和想法。

5 个答案:

答案 0 :(得分:8)

以下是我的建议:

Fiddle requiring no hacks

这是我们要包含的关键CSS:

@media (min-width:400px){
    .left {
        width: 60%;
    }
    .right {
        width: 30%;
        float: none;
        margin-left: 100%;
        transform: translateX(-100%);
    }
}

此CSS的说明

正在做的是将.right元素从容器中完全推出左侧,然后将它们拖回整个宽度。

position: relative;left: 100%;告诉元素它需要显示在容器的右边缘。

transform: translateX(-100%);然后告诉元素它需要向左显示(因此是负数)100%的宽度 - 它拖动它与你的右边齐平。

使用此解决方案,可以任意重新排序项目,无需进行其他计算。

我希望这有帮助!

更新

Fiddle requiring one hack not dependent on DOM order

以下是我们改变的内容:

<强> CSS

.right {
        width: 30%;
        float: none;
        margin-left: 100%;
        transform: translateX(-100%);
        margin-bottom: -1.2rem; /* New */
        margin-top: calc(1.2rem + 5px); /* New */
    }
    .right:first-of-type {
        margin-top: 0;    /*optional - if there's a preceding element on the page this will prevent it from being shifted downward*/
    }

这样做是让DOM认为这些元素在文档流程中占据的空间可以忽略不计,而实际上我们只是在利用它的边缘来使它显示在以前的位置。这个不应该在任意长的列表中使用任意排序的元素集失败。基本上我们做的事情与float在从文档流中删除元素时所做的非常类似 - 但我们只是将它保留为没有高度的空间。另外,它不会被拖到屏幕的一侧或另一侧。

calc(1.2rem + 5px)的{​​{1}}基本上是这样说的:添加我们带走的margin-top,加上我们以前的原始margin-bottom边距。

我在这里使用5px单位,因为您没有任何已定义的字体大小。通常,您会想要使用rem,我们可以在这里。我选择了em,因为这是这些项目的默认1.2。那么,此修复只适用于元素中的一行文本。您需要了解正在渲染的元素的高度才能使其正常工作。

希望有所帮助!

更新,第二个

Fiddling with minimal JavaScript

首先,添加:

<强> CSS

line-height

然后添加:

<强>的JavaScript

.right.last {
    margin-top: 0;
}

你不会再看到最后一个元素的差距了。

答案 1 :(得分:3)

我在这里再补充一个答案。我不想破坏之前的答案。然而,通过这个答案,包装div的必要性被消除了。

JSFiddle here

 <div class="left">left one</div>
 <div class="left">left two</div>
<div class="right">right one</div>
<div class="left">left three</div>
 <div class="right">right two</div>
 <div class="right">right three</div>
 <div class="right">right four</div>
 <div class="right">right five</div>

添加了float:left;clear : leftfloat:right;clear:right css属性

.left {float:left; background: coral; margin-bottom: 5px;}
.right {float:right; background: mediumaquamarine; margin-bottom: 5px;}

@media (max-width:400px){
    .left, .right  {
        width:100%;
    }
}
@media (min-width:400px){
    .left {
        float: left;
    clear : left;
    }
    .right {
        float: right;
        display: inline-block;
        margin-left: 10%;
    clear : right;
    }
}

答案 2 :(得分:1)

将所有左侧元素放在一个单独的div中。也是单独div中的正确元素。

然后像我在下面的代码片段中那样制作CSS样式。
有用!希望这是你所需要的!

&#13;
&#13;
.left {float:left; background: coral; margin-bottom: 5px;}
.right {float:right; background: mediumaquamarine; margin-bottom: 5px;}
.left-wrapper{ float:left; width:60%;}
.right-wrapper{ float:right; width:30%;}

@media (max-width:400px){
    .left, .right, .left-wrapper, .right-wrapper  {
        width:100%;
    }
}
@media (min-width:400px){
    .left {
        width: 100%;
    }
    .right {
        width: 100%;
        float: none;
        display: inline-block;
        margin-left: 10%;
    }
}
&#13;
<div class="left-wrapper">
<div class="left">left one</div>
<div class="left">left two</div>
<div class="left">left three</div>
</div>
<div class="right-wrapper">
<div class="right">right one</div>
<div class="right">right two</div>
<div class="right">right three</div>
<div class="right">right four</div>
<div class="right">right five</div>
</div>
&#13;
&#13;
&#13;

答案 3 :(得分:1)

如果您可以在右侧之前计算左侧前几个元素的高度(假设它从左侧开始),那么这将是可能的:http://jsfiddle.net/n467un0c/29/

.left { 
    float:none; 
    background: coral; 
    margin-bottom: 5px;
}

.right { 
    float:right; 
    background: mediumaquamarine; 
    margin-bottom: 5px;
    position: relative;
    top: -46px; /** this value should be the height of the elements added together (including the margins) on the left side BEFORE the first element on the right side... in this case it would be 'left one' and 'left two' before 'right one' **/
}

@media (max-width:400px){
    .left, .right  {
        width:100%;
    }
}
@media (min-width:400px){
    .left {
        width: 60%;
        margin-right: 10%;
    }
    .right {
        width: 30%;
        clear: right;
    }

答案 4 :(得分:0)

我更新了JSFiddle here。它现在正在运作。我已经为左div和右div添加了额外的包装。

<div class="left">
 <div class="left">left one</div>
 <div class="left">left two</div>
</div>
<div class="right">right one</div>
<div class="left">left three</div>
<div class="right">
 <div class="right">right two</div>
 <div class="right">right three</div>
 <div class="right">right four</div>
 <div class="right">right five</div>
</div>