Как распределить плавающие элементы равномерно с динамическим столбцом и числом строк в CSS?

У меня есть несколько div с фиксированной шириной и высотой (подумайте о каком-то вид каталога с картинками). Теперь я хочу показать им похожие на поведение float: left. Это гарантирует, что чем больше ваше окно браузера, тем больше divs отображаются в одной строке.

Недостатком решения float: left является то, что на правой стороне есть большой белый зазор, пока не будет соответствовать другой div. Теперь у меня есть работа по распределению divs равномерно по одной странице, а вместо большого белого пробела с правой стороны должны быть равномерно распределенные промежутки между отдельными div.

Решение в JavaScript легко: http://dl.dropbox.com/u/2719942/css/columns.html

Вы можете видеть, что при изменении размера окна браузера он ведет себя подобно float: left, но пространство равномерно распределяется между полями. Количество столбцов и строк динамически вычисляется с помощью JavaScript:

  function updateLayout() {
    var boxes = document.getElementsByClassName('box');
    var boxWidth = boxes[0].clientWidth;
    var boxHeight = boxes[0].clientHeight;
    var parentWidth = boxes[0].parentElement.clientWidth;

    // Calculate how many boxes can fit into one row
    var columns = Math.floor(parentWidth / boxWidth);

    // Calculate the space to distribute the boxes evenly
    var space = (parentWidth - (boxWidth * columns)) / columns;

    // Now let reorder the boxes to their new positions
    var col = 0;
    var row = 0;
    for (var i = 0; i < boxes.length; i++) {
      boxes[i].style.left = (col * (boxWidth + space)) + "px";
      boxes[i].style.top = (row * boxHeight) + "px";

      if (++col >= columns) {
        col = 0;
        row++;
      }
    }
  }

Теперь мне интересно, есть ли решение без JavaScript? Я бы предпочел решение только для CSS, потому что у меня будет возможно до сотни div на одной странице.

Я просмотрел CSS3 Flexible Box Layout, но это, по-видимому, полезно только для фиксированных макетов столбцов. В моем примере количество столбцов вычисляется динамически. Затем я попробовал CSS3 Multi-column Layout, который я мог бы получить что-то подобное, но divs выровнены по вертикали, отрезаны внутри, и поддержки браузера еще нет. Это кажется более полезным для текста, но в моем случае у меня есть фиксированные div с картинками, которые не должны прерываться.

Итак, мой вопрос: могу ли я реализовать что-то вроде этого без JavaScript?

Ответ 1

Ближайшее чистое решение CSS основано на text-align: justify.

Вот два из моих ответов, показывающих технику:

Вот демонстрационная версия вашего HTML/CSS: http://jsfiddle.net/thirtydot/5CJ5e/ (или полноэкранный режим)

Там разница в том, как ваш JavaScript и этот CSS обрабатывает последнюю строку, если существует другое количество полей по сравнению с другими строками.

Ваш JavaScript делает это:

Мой CSS делает это:

Если то, что делает CSS с другим числом ящиков в последней строке, неприемлемо, вы можете добавить дополнительные невидимые поля для завершения строки:

http://jsfiddle.net/thirtydot/5CJ5e/1/ (или полноэкранный режим)

У этого есть проблема, что невидимые поля увеличивают высоту содержащего элемента. Если это проблема, я не могу придумать способ ее исправить, не используя немного JavaScript:

http://jsfiddle.net/thirtydot/5CJ5e/2/ (или полноэкранный режим)

Конечно, поскольку JavaScript теперь используется, вы можете также использовать его для добавления невидимых ящиков в первую очередь (вместо того, чтобы судить HTML):

http://jsfiddle.net/thirtydot/5CJ5e/5/ (или полноэкранный режим)

(Я также написал более сложное исправление JavaScript для этого в более ранней редакции, прежде чем появилась идея невидимых ящиков для меня не должно быть причин использовать мое старое исправление сейчас.)

Ответ 2

Для этого вам нужно будет использовать Javascript.

Но просто отрегулируйте класс ящика, чтобы сразу корректировать поля всех ящиков.

// Calculate how many boxes can fit into one row
var columns = Math.floor(parentWidth / boxWidth);

// Calculate the space to distribute the boxes evenly
var space = (parentWidth - (boxWidth * columns)) / columns;

$('.boxClass').css('margin', space / 2);

-

Пример: http://jsfiddle.net/VLr45/1/

Ответ 3

Возможно, MASONRY может помочь с размещением?

Ответ 4

Итак, мой вопрос: могу ли я реализовать что-то подобное без JavaScript?

Недавно я прошел одно и то же упражнение и, наконец, сдался и использовал JavaScript. Даже отказавшись от IE 7 и 8 (что нецелесообразно), я не смог найти чистого решения CSS. Думаю, вы могли бы взломать длинный список медиа-запросов, чтобы сделать это ограниченным образом.

В итоге я написал небольшую (около 1 тыс. миниатюров) библиотеку, которая обрабатывает ширину, высоту, пропорциональное масштабирование, максимальную ширину, прокрутку, согласованные поля и дополнение и т.д.

Вот пример, в котором используется мой собственный код: http://jsfiddle.net/CmZju/2/. Я привел в пример пару сотен элементов.

Я бы предпочел решение только для CSS, потому что я, возможно, до сотни разделов на одной странице.

Механизм компоновки браузера должен будет выполнять те же (или подобные) вычисления, которые вы выполняете. Конечно, он сильно оптимизирован, но я бы тестировал ваше решение JS на нескольких старых компьютерах и нескольких мобильных устройствах, прежде чем делать скидку на него слишком медленно.

Похоже, вы используете абсолютное позиционирование. Мои неофициальные тесты показывают, что абсолютный макет значительно быстрее, чем вычисление поплавка. Это имеет смысл, если вы думаете о работе, которую браузер должен сделать, чтобы вычислить относительно размерный и плавающий элемент, а не просто рисовать элемент в определенном месте с определенными размерами.

Если вы действительно хотите оптимизировать производительность, вы можете манипулировать только видимым контентом. Это было бы намного сложнее, чем просто изменить размер всего и, вероятно, было бы актуальным только в том случае, если на странице было тысячи элементов.

Если вы перейдете по маршруту script, вы можете взглянуть на jQuery Masonry для получения дополнительных идей. Я слышал хорошие вещи об этом, и это дало мне хорошие идеи для моей собственной библиотеки.