2

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

Fraser
  • 14,036
  • 22
  • 73
  • 118
  • If all the divs are the same width it's impossible to have more than 4 per row `730/164 ~ 4`...You want to distribute them evenly I guess but not change the actual size of the children divs right? You might be able to do it with just CSS – elclanrs Jun 27 '12 at 04:33
  • If I understand your requirements correctly, I've already written a detailed answer: http://stackoverflow.com/questions/10548417/how-to-distribute-floated-elements-evenly-with-a-dynamic-column-and-row-count-in/10550660#10550660 – thirtydot Jun 27 '12 at 04:40
  • That is correct. Hence the requirement for more rows when I have more than 4 divs – Fraser Jun 27 '12 at 04:40
  • @thirtydot That's a nice solution, however I need to be able to space them out a bit more flexibly. The ideal fit is 4 on each row, however if I have 5 divs, I need to be able to put 3 on the top row and 2 on the bottom. all spaced evenly (to simplify slightly, the margin between the 2 on the bottom would be the same as the 3 on the top, however they would be centred) – Fraser Jun 27 '12 at 04:45
  • 1
    @Fraser: Some example images of what should happen with different numbers of elements would be extremely useful. – thirtydot Jun 27 '12 at 04:48
  • @thirtydot your wish is my command :) – Fraser Jun 27 '12 at 05:00
  • In the last example, is the extra space between elements significant? – thirtydot Jun 27 '12 at 05:02
  • I assume you mean the top and bottom margins of the small boxes? I just had to ask the designer about that. They can stay universal regardless of the left and right margin of the boxes. – Fraser Jun 27 '12 at 05:07

1 Answers1

1

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.

Community
  • 1
  • 1
chipcullen
  • 6,840
  • 1
  • 21
  • 17
  • You sir, are a saint. I'm heading in to the office now so will try it out and get back to you. Thanks again. – Fraser Jun 27 '12 at 20:30