balanced alternating column layout in CSS3

前端 未结 6 1702
无人共我
无人共我 2021-02-08 04:32

I\'m trying create a balanced (2-) column-layout.

The content is not text but blocks and varies in height. The content should be placed alternatingly left and right, as

相关标签:
6条回答
  • 2021-02-08 04:47

    PURE CSS SOLUTION:

    Add the following to your css file:

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

    DO NOT change your html or anything else.

    Result in FF:

    Firefox rendering

    --

    How it Works

    Instead of floating all your elements "left" and creating gaps, we float each container according to the side/column the element they reside in.

    0 讨论(0)
  • 2021-02-08 04:48

    I would say this is not possible without JS. Here is a fiddle I made based on an article from Ben Holland. At least to me looks like what you are after.

    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 #ffffd;
    }
    

    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);
    };
    
    0 讨论(0)
  • 2021-02-08 04:49

    You could try a mix of flex and float (only tested in Firefox/IE10 and safari 5.1.7 , cause to my own opinion, CSS is not your solution)

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

    But, in any CSS case you choose, the best is to relay on the mansonry script. CSS is not really adapted to this kind of layout. At this time you have many CSS method for layout and basicly: display and float.

    You can easily use this together within your html tree structure but this methods are not meant to be mixed. A boxe will be floatting, an inline-level-box or block-level-box and each are suppose to interact in the flow. Float, breaks a line before itself after a non floatting element or slides down untill it has enough room, that you dispatch right/left via CSS r not.

    inline-block moves away from floatting elements and breaks a line if not enough room left, floatting elements among inline-blocks will keep breaking a line before floating.

    Column CSS will fill columns with content one by one. see : http://codepen.io/gcyrillus/pen/AtazJ

    Inline-flex elements seems to work with floatting elements ... but is it suppose to untill it's a validated rule ?

    What seems to be wised to me , is to used a javascript for the layout expected and relay on float or display:inline-block + width as a fall back.

    Last solution is to think this ahead on your server side and dispatch your items in 2 containers with another appropriate markup if that is possible ( no idea of your real life content dispatched in your ol li ).

    The CSS for the FLEX test :

    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;
    }
    
    0 讨论(0)
  • 2021-02-08 04:57

    I'm not sure if I got this right . .

    "the 2's should stand alone on the right side and the 1, 3's and 4 should stand on the left side (without space between them)."

    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/

    This is pure css. Everything is floated left then gave inline-css to float:right on the div with (4) 2's

    I kinda don't know how to set the inline-css without javascript. Server side maybe? but I doubt you can get the height of the elements.

    Well anyway hope this helps.

    0 讨论(0)
  • 2021-02-08 04:58

    EDIT: This is an interesting solution, but unfortunately it does not solve the problem that was asked for.

    The solution I propose here puts subsequent elements into alternating columns, so: 1 -> left, 2 -> right, 3 -> left, 4 -> right, etc.

    This is a interesting problem by itself, but not what was asked for.

    Thanks to @Nils in the comments for pointing this out.

    Original answer

    Here is my attempt with flex!
    https://jsfiddle.net/vqLr8t3e/

    I am not sure if it works in IE11.

    Code

    .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>

    Idea

    Use flex-direction: column; and flex-wrap: wrap; on the container, and width: 50%; on the items, as a first step towards showing the items in columns.

    Use order: -1; and order: 1 to sort odd and even elements into different columns.

    Use a gratuitous margin-top: 10000px; on the first element of each column, and a max-height: 19999px; on the container, so that no two such items fit into one column. This will make sure each of these items starts in a new column. Compensate with a negative margin-top on the container. Cut it off with an outer container with overflow: hidden;.

    0 讨论(0)
  • 2021-02-08 05:02

    Updated: I believe this is almost impossible to achieve with CSS only. There are many different solutions, but they all require some compromises unless you are willing to use JavaScript or some server-side code.

    Using CSS columns

    Here's an alternate fiddle using reordered blocks. Here's a fiddle demo using CSS columns without reordering.

    You can use CSS colunms to change your block flow to vertical unless you alter the order of their output. If you can output odd numbers first, then even numbers, you win.

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

    This solution is not compatible with IE9 and below.

    Block Height Known

    If you do know your block heights you can solve this problem by using absolute positioning.

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

    A big drawback is dynamic content; we seldom know block height. So this solution is very limited in its application unless you are willing to calculate the height block height.

    If you are willing to use JS

    Use a plugin like Masonry. Both in vanilla js or jQuery flavour.

    Other Options

    This leaves you with the following options that require some compromises.

    1. Group your blocks into columns. See this Fiddle for a demo. This will alter the flow of your blocks to vertical, then horizontal.

    2. Use display: inline-block; vertical-align: top; on your blocks. This will leave some white space below your blocks.

    3. Force the height of your blocks, rendering this a non-issue. For blocks with additional content use the overflow property to allow in-block scrolling.

    4. As others have commented, you could attempt to calculate the height of the blocks on the server.

    0 讨论(0)
提交回复
热议问题