Вот мое решение.Сначала нам нужно найти ширину столбца наименьших с заданным знаменателем.Это будет 1/2, 1/3 и так один.Для этого нам необходимо вычесть количество возможных полей из ширины (которая равна: (знаменатель минус один), умноженной на маржу ) и разделить ее на знаменатель.
Это даст нам:Width - Margin * (Denominator - 1)) / Denominator
.
Теперь у нас есть ширина столбца наименьшая.Если мы хотим получить ширину для большего столбца, мы должны умножить эту сумму на Числитель.
(Width - Margin * (Denominator - 1)) / Denominator) * Numerator
Остается проблема: если у вас есть столбец 3/4это должна быть расчетная ширина плюс два раза запас.Чтобы достичь этого, мы добавим поле, умноженное на (числитель минус один)
(Numerator - 1) * Margin
Результирующая формула:
((Width - Margin * (Denominator - 1)) / Denominator) * Numerator + ((Numerator - 1) * Margin)
После вычисления ширины нам необходимо применить очищающий элемент после текущего столбца, если общая ширина текущей строки превышает 80% доступной ширины (поскольку мы допускаем столбец наименьшего размера 1/5)очищающий элемент перед текущим столбцом, если общая ширина превышает доступную ширину.
Рабочий пример можно найти здесь: http://jsfiddle.net/UNvyd/
HTML:
<div id="wrapper" data-smallesColumn="5">
<div class="column" data-width="1/2"></div>
<div class="column" data-width="1/2"></div>
<div class="column" data-width="1/3"></div>
<div class="column" data-width="1/3"></div>
<div class="column" data-width="1/3"></div>
<div class="column" data-width="1/4"></div>
<div class="column" data-width="1/4"></div>
<div class="column" data-width="2/4"></div>
<div class="column" data-width="1/4"></div>
<div class="column" data-width="1/5"></div>
<div class="column" data-width="1/5"></div>
<div class="column" data-width="1/5"></div>
<div class="column" data-width="1/5"></div>
<div class="column" data-width="1/5"></div>
<div class="column" data-width="1/2"></div>
<div class="column" data-width="1/4"></div>
<div class="column" data-width="1/4"></div>
<div class="column" data-width="1/3"></div>
<div class="column" data-width="2/3"></div>
<div class="column" data-width="3/4"></div>
<div class="column" data-width="1/4"></div>
<div class="column" data-width="2/5"></div>
<div class="column" data-width="3/5"></div>
<div class="column" data-width="2/5"></div>
<div class="column" data-width="1/5"></div>
<div class="column" data-width="2/5"></div>
<div class="column" data-width="1/2"></div>
<div class="column" data-width="1/3"></div>
<div class="column" data-width="1/4"></div>
<div class="column" data-width="4/5"></div>
<div class="clear"></div>
</div>
CSS:
#wrapper {
width:423px;
background-color:red;
}
.column {
height:20px;
float:left;
margin-right:18px;
background-color:yellow;
overflow-x:hidden;
}
.clear {
clear:both;
height:2px;
background-color:green;
}
Javascript:
$(document).ready(function() {
var gi_wrapperWidth = $('#wrapper').innerWidth();
var gi_columnMargin = parseInt($('.column').css('margin-right'));
var gi_maxWidth = (gi_wrapperWidth - 4 * gi_columnMargin) * 0.8 + gi_columnMargin;
var gi_elCount = 0;
var gi_widthCount = 0;
$('.column').each(function(){
gi_elCount++;
var lo_that = $(this);
//Get the intended width
var ls_dataWidth = lo_that.data('width');
//Split x/y into x and y
var la_widthArray = ls_dataWidth.split('/');
var li_numerator = la_widthArray[0];
var li_denominator = la_widthArray[1];
//Do some math!
//((Width - Margin * (Denominator - 1)) / Denominator) * Numerator + ((Numerator - 1) * Margin)
var li_elWidth = ((gi_wrapperWidth - gi_columnMargin * (li_denominator - 1)) / li_denominator) * li_numerator + ((li_numerator - 1) * gi_columnMargin);
li_elWidth = parseFloat(li_elWidth.toFixed(2));
//Set the width and show it inside the element
lo_that.css('width', li_elWidth+'px').html(li_elWidth+'px');
gi_widthCount += li_elWidth;
if (Math.floor(gi_widthCount) > (gi_wrapperWidth - ((gi_elCount-1) * gi_columnMargin))) {
gi_widthCount = li_elWidth;
gi_elCount = 1;
lo_that.before('<div class="clear"></div>');
}
else if (Math.floor(gi_widthCount) > gi_maxWidth) {
lo_that.css('margin-right', '0px');
gi_widthCount = 0;
gi_elCount = 0;
lo_that.after('<div class="clear"></div>');
}
});
});
Формула может нуждаться в улучшениях, но я доволен результатом, поэтому я буду придерживаться этого.
Я рекомендую не использовать это как js, но как решение на стороне php / server.