Fraser
Fraser

Reputation: 14244

Dynamically laying out fixed size divs depending on their number

Bit of a puzzle for you....

I have a 730px wide, auto height div. Inside this I have will number of smaller divs 164px X 261px.

These will be pulled in to the template dynamically so I could have 1, or I could have 18 or for the sake of this excercise, I could have 1000 or anywhere in between.

I need to space these out so that on each line there is an equal distance between each. Simple if we are dealing with up to 4, I could do something like:

var totalWidth = $('.bigDiv .smallerDivs').length * $('.bigDiv .smallerDivs').width();
var margin = ($('.bigDiv').width - totalWidth) / ($('.bigDiv .smallerDivs').length * 2);
$('.bigDiv .smallerDivs').css('margin-left': margin , 'margin-right': margin);

However, when there are say 5. I want to have 3 on the top row and 2 on the bottom. Or if I have 7, I would like 4 on top 3 on bottom. If there are 11 I would like 4 on top, 4 in the middle and 3 below etc etc etc, each row nicely justified based on however many small boxes there are.

Can anyone suggest a nice clean way I may go about this?

enter image description here

Upvotes: 2

Views: 251

Answers (1)

chipcullen
chipcullen

Reputation: 6960

My answer is basically based on the logic found in this post's answer.

The overall concept is that you can evaluate what the number of divs are divisible by, then attach a class to the larger div, which you can use to space your inner divs out.

$(document).ready(function(){
  function nos_div_eval(val,container,inner){
    var nosDivs = $(inner).length;
     for(var i=val; i>1; i--){
      if (nosDivs % i === 0) {
        $(container).addClass('div_by_' + i);
        break;
      } else {
       $(container).addClass('prime');
      }  
     }
   }

   nos_div_eval(10, '.bigDiv', '.smallerDivs');

});​

This will evaluate the number of small divs, and see if it is divisible by any number between 2 and 10. If it matches, it adds a class like .div_by_3 to the outer <div>. It will add a class based on the largest number between 2 and 10 that it is divisible by. That way you can set up your styles like this:

.bigDiv.div_by_3 .smallerDivs {
   margin-right: 40px;
 }

 .bigDiv.div_by_4 .smallerDivs {
   margin-right: 20px;
  }

You can adjust the margin amounts in order to get the divs to break into the rows that you want.

However, if the number of smaller divs are not divisible by a number between 2 and 10, this function will add a class called "prime", because odds are it's a prime number. You can add some arbitrary margin value to those divs and live with what happens.

If you really want to cover your bases, you can change the initial value of "i" - you can set it to 31, which is the largest number that has a square less than 1000. I just thought that would make the for loop really long.

This fiddle demonstrates the logic, though I simplified it a little to make it more clear. You can add <div>'s to it and see the new alert value.

EDIT: okay, I couldn't leave well enough alone, I've gone back and make the function wrapped up on it's own, with three parameters. The first parameter is the upper value you want to check against, then the container element, then the inner elements. Be sure to include '#' or '.' depending on whether the elements have ID's or classes - this will also work with plain ol' elements as well.

Upvotes: 1

Related Questions