4

I got the following HTML page with just a couple of DIV-elements. These elements are generated with random values for the left margin.

Additional Info: The DIV-elements in the HTML file have to stay in the given order.

<html>
<head>
    <style type="text/css">
        .box{
            height: 50px; width: 50px; border: 1px solid black; 
            text-align: center; margin-bottom: 5px;
        }
    </style>
    <title></title>
</head>
<body>
    <div class="box">1</div>
    <div class="box" style="margin-left: 30px">2</div>
    <div class="box" style="margin-left: 90px">3</div>
    <div class="box" style="margin-left: 120px">4</div>
    <div class="box" style="margin-left: 240px">5</div>
</body>
</html>

The resulting page looks like this:

actual page layout

Is there a way, to align the DIV-elemets to the top of the page with pure CSS? DIV-elements should stack up, if they aren't completely beside the preceding DIV. That is why element 2 and 4 are in the second row. Since there is no 'float: top;' command, I have no idea how to achieve the following layout:

desired page layout

Since my problem is still not clear, here is another example to clarify, that the layout should work with random generated DIV-elements:

enter image description here

If the element does not fit beside the preceding element, it should stack up. If it fits, it should align to the top.

If there is no way with pure CSS, a JS workaround would also be possible.

benny.la
  • 1,212
  • 12
  • 26
  • Why don't you just use `float: left`? – AfromanJ Nov 18 '13 at 13:13
  • 1
    Because he wants his div to float on top, look at the second picture. – OlivierH Nov 18 '13 at 13:14
  • 2
    possible duplicate of [How can I make a float top with CSS?](http://stackoverflow.com/questions/1847460/how-can-i-make-a-float-top-with-css) – OlivierH Nov 18 '13 at 13:15
  • 1
    use `display:inline` it works – Kaushik Nov 18 '13 at 13:15
  • 1
    Why's the second one on the second line? This hardly seems like a floating to the top? – Liam Nov 18 '13 at 13:15
  • the problem you've got is what happens when the screen gets smaller or bigger? Shrink your browser window to see what I mean. It's very unclear what you actually want. – Liam Nov 18 '13 at 13:28
  • Unfortunately my explanations were incomplete. The resulting layout should look like picture 2, that means, that DIV-elements should stack if they aren't completely beside the preceding DIV. That is why element 2 and 4 are in the second row. 'display: inline-block;' results in an one-row solution. – benny.la Nov 18 '13 at 13:32
  • @OlivierH it is not a duplicate, because the answer with columns in the linked post does not work for random margins of the div. – benny.la Nov 18 '13 at 13:43

3 Answers3

0

You can either apply a float: left to the .box class or set its display value to inline-block, unless there's a reason elements 2 and 4 in your diagram have to be below 1, 3, and 5.

There's no float: top because it's not strictly required. divs are block elements, which means that in the normal flow of the document, they appear beneath one another, according to their placement in your HTML. There's a hybrid display value that I mentioned above, inline-block, which has block-like qualities but displays the elements in a horizontal fashion.

If you require that certain elements on your page "float" up or down (in the every day sense of the word), you might try applying a margin-top to the elements that need be be lower?

Chase Ries
  • 2,094
  • 2
  • 15
  • 16
0

You have to use float:left; and re-arrange divs

<table><tr>
  <td><div class="box">1</div></td>
  <td><div class="box" style="margin-left: 30px;">2</div></td>
  <td><div class="box" style="margin-left: 90px">4</div></td>
  <td><div class="box" style="margin-left: 120px">3</div></td>
  <td><div class="box" style="margin-left: 240px">5</div></td>
</tr></table>


    <style>
    table{width:100%;}
table td{
    height:120px;
}
table td:nth-child(1n){
    vertical-align:top;
}
table td:nth-child(2n){
    vertical-align:bottom;
}
.box{        
    height: 50px;
    width: 50px;
    border: 1px solid black; 
    text-align: center;
    margin-bottom: 5px;
}
    </style>

Please check jsfiddle demo

Parixit
  • 3,829
  • 3
  • 37
  • 61
  • 1
    Please provide some code, not only a fiddle link, to prevent future broken links. – zessx Nov 18 '13 at 13:25
  • this solution only works if you reorder the DIVs manually. In my example there could be up to a hundred random generated DIVs. – benny.la Nov 18 '13 at 13:38
  • @benny.la You can achieve this by using ``
    – Parixit Nov 18 '13 at 14:06
  • @Parixit I cannot think of a solution with the -hint that fits my needs. Can you give me more information on this? Remember: I cannot sort the elements, and the number of elements and the left margin of them is random.
    – benny.la Nov 18 '13 at 14:16
  • @benny.la Please check my update. I want to say something like this. – Parixit Nov 18 '13 at 15:34
  • @Parixit this still not works with random generated DIV-elements. It only works if the DIVs are alternately float to the top and bottom. Look at my initial question, I updated it with another example. – benny.la Nov 19 '13 at 09:04
  • @benny.la Then probably you should go with the javascript according to your need, you do a calculation and resolve it. – Parixit Nov 19 '13 at 09:19
  • 1
    @Parixit hmmm... too bad, that it is apparently not possible to do it with CSS. Anyway, thx for the ideas! – benny.la Nov 19 '13 at 09:21
0

You can call this javascript function once the page is loaded (<body onload="float_top()">) :

var top = 5; // top value for next row
var margin = 5; // space between rows
var rows = []; // list of rows
function float_top() {
    for (var c = 0; c < document.body.children.length; c++) {
        var ok = false;
        var child = document.body.children[c];
        var cr = child.getBoundingClientRect();
        for (var i = 0; i < rows.length; i++) {
            if (cr.left > rows[i].right) {
                rows[i].right = cr.right;
                child.style.top = rows[i].top + "px";
                ok = true;
                break;
            }
            if (cr.right < rows[i].left) {
                rows[i].left = cr.left;
                child.style.top = rows[i].top + "px";
                ok = true;
                break;
            }
        }
        if (!ok) {
            // add new row
            rows.push({
                top: top,
                right: cr.right,
                left: cr.left
            });
            child.style.top = top + "px";
            top = child.getBoundingClientRect().bottom + margin;
        }
    }
}

It iterates over the divs, keeps track of the space used by each div and adds "rows" when there's no more space to put a div in the existing rows.

See this jsFiddle.

Note:

  • for this to work, the position of the divs must be set to absolute
  • the divs are assumed to be the same height. You'll need some tweaking if it's not the case.
Rémi Svahn
  • 123
  • 5