Is it possible to stack unlimited divs left or right arbitrarily without a wrapper?

后端 未结 5 1236
情深已故
情深已故 2021-02-13 20:31

I thought this would be (relatively) easy, but from the answers it seems harder than I anticipated.

Perhaps even impossible!

GOAL

I\'d

相关标签:
5条回答
  • 2021-02-13 21:13

    Put all the left side elements inside a separate div. Also the right elements inside a separate div.

    Then make the css styling as i did in below code snippet.
    It works! Hope this is what you need!

    .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%;
        }
    }
    <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>

    0 讨论(0)
  • 2021-02-13 21:18

    I have updated the JSFiddle here. It is working now. I have added extra wrappers to the left divs and right divs.

    <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>
    
    0 讨论(0)
  • 2021-02-13 21:22

    If you can figure out the height of the first few elements on the left side (assuming it starts with the left side) before the right side then this would be possible: 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;
        }
    
    0 讨论(0)
  • 2021-02-13 21:29

    Here's what I'd recommend:

    Fiddle requiring no hacks

    Here's the key CSS that we're including:

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

    Explanation of this CSS

    What that's doing is pushing your .right elements completely out of the container to the left, and then dragging them back their entire width.

    The position: relative; and left: 100%; tell the element that it needs to display off the right edge of the container.

    The transform: translateX(-100%); then tells the element that it needs to display to the left (hence the negative) 100% of its width - which drags it to be flush with your right edge.

    With this solution, items can be reordered arbitrarily and no additional calculations need to be made.

    I hope this helps!

    Update:

    Fiddle requiring one hack not dependent on DOM order

    Here's what we changed:

    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*/
        }
    

    What this is doing is making the DOM think these elements have negligible space they're taking up in the document flow, when in reality we're just screwing with its margins to make it display where it was before. This shouldn't fail with an arbitrarily ordered set of elements in an arbitrarily long list. Essentially we're doing something very similar to what float does in removing the element from document flow - but we're only making it reserve space as if it had no height. Plus, it doesn't get dragged to one side of the screen or the other.

    The calc(1.2rem + 5px) for margin-top is basically saying: add this margin-bottom we took away back, plus the original 5px margin we had before.

    I use rem units here because you don't have any defined font-sizes. Generally, you would want to use em, and we could have here. I chose 1.2 as that's the default line-height for these items. This fix, then, would only work for one line of text in an element. You'll need to have some awareness of the height of the element being rendered in order for this to work.

    Hope that helps!

    Update, the second

    Fiddling with minimal JavaScript

    First, add this:

    CSS

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

    Then add this:

    JavaScript

    var rights = document.querySelectorAll(".right");
    rights[rights.length-1].className += " last";
    

    And you won't see that gap on the last element any longer.

    0 讨论(0)
  • 2021-02-13 21:30

    I am adding one more answer here. I don't want to spoil the previous answer. However, with this answer the necessity to wrap the divs is eliminated.

    JSFiddle here

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

    Added float:left;clear : left and float:right;clear:right css properties

    .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;
        }
    }
    
    0 讨论(0)
提交回复
热议问题