SitePoint Sponsor

User Tag List

Results 1 to 5 of 5
  1. #1
    SitePoint Member
    Join Date
    May 2009
    Posts
    13
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Can't properly position multy column grid with Javascript

    Hi everyone,

    I have a set of divs with different heights - all absolutely positioned within the main div container. Number of columns is supposed to be customizable and it should depend on the window width. I can't make it working. Could anyone let me know what is wrong with the code? Thank you.

    HTML Code:
    <div id="grid_container">
        <div style="height: 140px;"><div>1</div></div>
        <div style="height: 200px;"><div>2</div></div>
        <div style="height: 120px;"><div>3</div></div>
        <div style="height: 180px;"><div>4</div></div>
        <div style="height: 150px;"><div>5</div></div>
        <div style="height: 160px;"><div>6</div></div>
        <div style="height: 180px;"><div>7</div></div>
        <div style="height: 170px;"><div>8</div></div>
        <div style="height: 160px;"><div>9</div></div>
        <div style="height: 180px;"><div>10</div></div>
        <div style="height: 150px;"><div>11</div></div>
        <div style="height: 160px;"><div>12</div></div>
        <div style="height: 130px;"><div>13</div></div>
        <div style="height: 140px;"><div>14</div></div>
        <div style="height: 210px;"><div>15</div></div>
    </div>

    Code:
    window.addEventListener('load', renderGrid, false);
    window.addEventListener('resize', renderGrid, false);
    
    function renderGrid(){
    			
    	var blocks = document.getElementById("grid_container").children;
    	var pad = 10, cols, newleft, newtop;
    		
    	if(window.innerWidth<400){
    		cols = 2;
    	}
    	else{
    		cols = 3;
    	}
    				
    	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";
    				
    		}		
    	}
    }

  2. #2
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,832
    Mentioned
    25 Post(s)
    Tagged
    1 Thread(s)
    I can't see anywhere in that code where you set the divs as position:absolute

    Also from my understanding of what you are trying to do the arrangement of the divs would be far easier to do with CSS without any JavaScript involvement at all.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  3. #3
    SitePoint Enthusiast
    Join Date
    Feb 2014
    Posts
    41
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Would something like this serve your purposes? (Try that out and resize the browser).

    Try something like this:
    Code:
    <!DOCTYPE html>
    <style>
    .r { background: red; }
    .g {background: green; }
    .b {background: blue; }
    div { height: 100px; float: left; width: 100px }
    </style>
    <div class="r">1</div>
    <div class="g">2</div>
    <div class="b">3</div>
    <div class="r">4</div>
    <div class="g">5</div>
    <div class="b">6</div>
    <div class="r">7</div>
    <div class="g">8</div>
    <div class="b">9</div>
    <div class="r">10</div>
    <div class="g">11</div>
    <div class="b">12</div>

  4. #4
    SitePoint Member
    Join Date
    May 2009
    Posts
    13
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you for your response. I know it might be easier to do it with CSS, but it's almost done already and it doesn't look overwhelming doing it with JavaScript. Here is the code that it looks like it should work but it doesn't:
    Code:
    if(window.innerWidth<400){
    	cols = 2;
    }
    else{
    	cols = 3;
    }

    Here is the CSS:

    Code:
    <style type="text/css">
    div#grid_container{
    	width: 900px;
    	margin: 0px auto;
    	height: 860px;
    	border: #999 1px dashed;
    }
    div#grid_container > div{
    	position: absolute;
    	width: 291px;
    	border: #000 1px solid;
    }	
    div#grid_container > div:nth-child(2n+0){
    	background: #FFDC64;
    }
    div#grid_container > div:nth-child(2n+1){
    	background: #FEC910;
    }
    div#grid_container > div > div{
    	padding: 20px;
    	font-size: 27px;
    	color: #D9A800;
    }
    </style>
    Thanks again.

    Thank you for your response. All divs have different heights so floating left wouldn't work.
    Last edited by Mittineague; Feb 18, 2014 at 18:34.

  5. #5
    SitePoint Enthusiast
    Join Date
    Feb 2014
    Posts
    41
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    How about this:
    HTML Code:
    <!DOCTYPE html>
    <style>
    .r { background: red; }
    .g {background: green; }
    .b {background: blue; }
    div { float: left; width: 100px }
    body > div { height:110px; background:#aaa; }
    </style>
    <body>
    <div><div class="r" style="height:100px">1</div></div>
    <div><div class="g" style="height:40px">2</div></div>
    <div><div class="b" style="height:60px">3</div></div>
    <div><div class="r" style="height:50px">4</div></div>
    <div><div class="g" style="height:30px">5</div></div>
    <div><div class="b" style="height:110px">6</div></div>
    <div><div class="r" style="height:40px">7</div></div>
    <div><div class="g" style="height:60px">8</div></div>
    <div><div class="b" style="height:80px">9</div></div>
    <div><div class="r" style="height:30px">10</div></div>
    <div><div class="g" style="height:50px">11</div></div>
    <div><div class="b" style="height:70px">12</div></div>
    </body>
    I know it might be easier to do it with CSS, but it's almost done already
    The principle reason Iím posting CSS-based solutions is because I donít really understand the behavior you want and that makes it very difficult to work out whatís wrong with your JavaScript. Not that I couldnít do it but so far when I try to write your code I donít manage to get far enough to see what you are doing wrong before my mind baulks and goes ďHang on couldnít this just be done with CSS?!Ē

    In this case I believe this laziness on my part actually coincides with the better way to do it and it sounds as if you are suffering from some sunk cost bias. So I would like to point out, if there is an acceptable CSS-based solution, then that is definitely your better option. Not just because it is considerably easier but it will play better with other page elements, have better performance, and be easier to change later. If the code Iíve just posted provides the behavior youíre seeking I recommend you throw away your JavaScript and forget about it; thereíll be plenty of other opportunities to write JavaScript.

    Let me know, however, if this most recent CSS-based solution of mine doesnít give you the behavior you are looking for.


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •