0

I am trying to implement a javascript grid gallery, however the boxes float out of the container, and thus over the elements that should come after the gallery. I tried wrapping another DIV around the entire grid container, or adding clearfixes, but without success.

enter image description here

JSFiddle: https://jsfiddle.net/ssdfjoLp/ (however does not render the grid layout correctly, dunno why)

Javascript:

function renderGrid(){
var blocks = document.getElementById("grid_container").children;
var pad = 0, cols = 3, newleft, newtop;
for(var i = 1; i < blocks.length; i++){
if (i % cols == 0) {
newtop = (blocks[i-cols].offsetTop + blocks[i-cols].offsetHeight) + pad;
blocks[i].style.top = newtop+"px";
} else {
if(blocks[i-cols]){
newtop = (blocks[i-cols].offsetTop + blocks[i-cols].offsetHeight) + pad;
blocks[i].style.top = newtop+"px";
}
newleft = (blocks[i-1].offsetLeft + blocks[i-1].offsetWidth) + pad;
blocks[i].style.left = newleft+"px";    
}
} 
}
window.addEventListener("load", renderGrid, false);
window.addEventListener("resize", renderGrid, false);

CSS:

#grid_container{
position:relative;
width:100%;
margin:0px auto;
height: auto;
}
.grid-item{
position:absolute;
width: 33.33333%;
border: #000 1px solid;
}
.grid-item:nth-child(2n+0) {
background: #FFDC64;
}
.grid-item:nth-child(2n+1) {
background: #FEC910;
}
#grid_container .grid-item > div{
padding: 20px;
font-size: 27px;
color:#D9A800;
}

HTML:

<div id="grid_container_holder">
<div id="grid_container">
  <div class="grid-item" style="height:140px;"> <div>1</div> </div>
  <div class="grid-item" style="height:200px;"> <div>2</div> </div>
  <div class="grid-item" style="height:120px;"> <div>3</div> </div>
  <div class="grid-item" style="height:180px;"> <div>4</div> </div>
  <div class="grid-item" style="height:150px;"> <div>5</div> </div>
  <div class="grid-item" style="height:110px;"> <div>6</div> </div>
  <div class="grid-item" style="height:180px;"> <div>7</div> </div>
  <div class="grid-item" style="height:170px;"> <div>8</div> </div>
  <div class="grid-item" style="height:150px;"> <div>9</div> </div>
  <div class="grid-item" style="height:180px;"> <div>10</div> </div>
  <div class="grid-item" style="height:150px;"> <div>11</div> </div>
  <div class="grid-item" style="height:160px;"> <div>12</div> </div>
  <div class="grid-item" style="height:140px;"> <div>13</div> </div>
  <div class="grid-item" style="height:140px;"> <div>14</div> </div>
  <div class="grid-item" style="height:220px;"> <div>15</div> </div>
</div><!--grid-->
</div><!--grid holder-->
<div>Section to come after gallery items</div>
rainerbrunotte
  • 907
  • 1
  • 17
  • 37
  • The text isn't visible because of your `.grid-item{position:absolute}` property – NTL Jun 03 '16 at 13:09

1 Answers1

1

It actually works. Check it out: https://jsfiddle.net/ssdfjoLp/1/

Two problems:

  1. You have to add jquery to jsfiddle
  2. jsfiddle executes javascript onload by default. Either get rid of window.addEventListener("load", renderGrid, false); or just use renderGrid() without the addEventListener

To get the footer rendered after the masonry, you will need to manually set the height of the container based on the maximum height of the lowest grid-item. You will need to finetune it, but this works: https://jsfiddle.net/ssdfjoLp/3/

function renderGrid(){
    var blocks = document.getElementById("grid_container").children;
    var pad = 0, cols = 3, newleft, newtop;

    var max_height = 0;

    for(var i = 1; i < blocks.length; i++){
        if (i % cols == 0) {
            newtop = (blocks[i-cols].offsetTop + blocks[i-cols].offsetHeight) + pad;

            // Get maximum height plus item height
            max_height = Math.max(max_height, newtop + blocks[i-cols].offsetHeight)

            blocks[i].style.top = newtop+"px";
        } else {
            if(blocks[i-cols]){
                newtop = (blocks[i-cols].offsetTop + blocks[i-cols].offsetHeight) + pad;
                blocks[i].style.top = newtop+"px";
            }
            newleft = (blocks[i-1].offsetLeft + blocks[i-1].offsetWidth) + pad;
            blocks[i].style.left = newleft+"px";
        }
    }

    // Set the height of grid_container
    $('#grid_container').css('height', max_height)
}
window.addEventListener("load", renderGrid, false);
window.addEventListener("resize", renderGrid, false);

var totalheight = $('#grid_container').height();
$('#heightholder').html('container height: '+totalheight+'px');
Martin Gottweis
  • 2,721
  • 13
  • 27
  • thanks, i have updated the function on jsfiddle. however, now it shows the problem clearly, the footer sentence gets hidden by the grid ... – rainerbrunotte Jun 03 '16 at 17:28
  • updated the answer to move the footer down. Thing is, if you use `position: absolute`, the element than will have no effect on other elements. So you have to set the height of the container which is not absolute and will move other elements down. – Martin Gottweis Jun 04 '16 at 08:11
  • hi again, i have just noticed that the height correction does not work when there are less than 4 items in the gallery? do you have any idea on how to adjust this problem? i tried getting around with it by getting the height of each column (by taking the offsetHeight and offsetTop from every last child div in each column), but it does not work when there is only 1 items in the gallery. It is driving me nuts. See here http://stackoverflow.com/questions/38834843/javascript-element-offsetheight-returns-returns-0-in-for-loop – rainerbrunotte Aug 08 '16 at 20:10
  • @rainerbrunotte: Could you maybe share a non-working fiddle? – Martin Gottweis Aug 09 '16 at 06:33
  • hi, here is the non-working https://jsfiddle.net/0otvhgkg/, basically a copy of the one you created back then, but i removed the style="height:xxx" attribute from the grid items (as i want them to be dynamic). you will see that as soon as you add another grid item div after item 3, the grid works fine, but if there are only 3, it breaks .... – rainerbrunotte Aug 10 '16 at 08:12
  • Posted the code in the new question. Hope it works for you – Martin Gottweis Aug 10 '16 at 09:19
  • thanks so much for that! however it only works if there are 2 blocks minimum, if there is only one, it still breaks: https://jsfiddle.net/0otvhgkg/4/ – rainerbrunotte Aug 10 '16 at 09:38