Умные динамические колонки с применением CSS и jQuery

Существует два типа колонок, используемых на веб-сайтах: фиксированной ширины и тянущиеся в ширину в зависимости от размера экрана (их еще называют “резиновыми”).

Недостатком фиксированных колонок при их использовании в “резиновом” блоке является то, что может появляться лишнее незаполненное пространство (при определенной ширине блока), поскольку его ширина меньше ширины столбца:

Фиксированные колонки

“Резиновые” же колонки не оставляют избыточных пустого пространства и прекрасно вписываются в родительский блок. Однако их недостаток заключается в том, что в строку мы можем поместить только фиксированное число столбцов:

''Резиновые'' колонки

Решение

Суть решения заключается в том, чтобы взять преимущества обоих ситуаций и объединить их в одно. Что мы должны получить в итоге:

  • Блок должен вмещать столько фиксированных колонок, сколько позволяет размер экрана.
  • Если в блоке образовалось лишнее свободное пространство, равномерно распределить его на каждую из колонок, чтобы заполнилось все свободное пространство в блоке.
  • При растяжении колонок ориентироваться на их базовую ширину и растягивать их до той поры, пока потенциальное свободное пространство не вместит очередную колонку.

Умные колонки

Посмотреть пример – Умные динамические колонки.

HTML

Начнем с создания неупорядоченного списка, пункты которого будут вести себя как колонки.

<ul class="column">
	<!-- повторяющийся элемент списка -->
	<li>
		<div class="block">
		<!-- контент -->
		</div>
	</li>
	<!-- конец повторяющегося элемента -->
</ul>

CSS

ul.column{
	width: 100%;
	padding: 0;
	margin: 10px 0;
	list-style: none;
}
ul.column li {
	float: left;
	width: 200px; /* ширина колонки по умолчанию */
	padding: 0;
	margin: 5px 0;
	display: inline;
}
.block {
	height: 355px;
	font-size: 1em;
	margin-right: 10px; /* отступ между колонками */
	padding: 20px;
	background: #e3e1d5;
}
.block h2 {
	font-size: 1.8em;
}
.block img {
	/* параметры для изображений с меняющимися размерами и бордюром */
	width: 89%; /* убираем 1% от ширины, чтобы предотвратить баг в IE6 */
	padding: 5%;
	background:#fff;
	margin: 0 auto;
	display: block;
	-ms-interpolation-mode: bicubic; /* предотвращение пикселизации изображений в IE 6/7 */
}

jQuery


function smartColumns() { //функция, подсчитывающая ширину колонок

	//сброс ширины строки до 100% после изменения размера экрана
	$("ul.column").css({ 'width' : "100%"});

	var colWrap = $("ul.column").width(); //определяем ширину строки
	var colNum = Math.floor(colWrap / 200); //определяем, сколько столбцов в 200px вместится в строку и округляем число до целого
	var colFixed = Math.floor(colWrap / colNum); //ширину строки делим на количество столбцов, округляем до целого числа, в результате получаем точную скорректированную ширину колонки

	$("ul.column").css({ 'width' : colWrap}); //ставим точную ширину строки в пикселях вместо использования % - это предотвратит возможные баги в разных браузерах при различных разрешениях экрана
	$("ul.column li").css({ 'width' : colFixed}); //ставим точную ширину измененным столбцам

}

smartColumns(); //запускаем функцию после загрузки страницы

$(window).resize(function () { //запускаем функцию после каждого изменения размера экрана
	smartColumns();
});

Ссылки по теме

P.S. Довольно интересная штука. При удобном случае нужно будет обязательно воспользоваться.

Комментарии (54)

  1. sordes
    30 мая 2009 г. в 13:35

    Может, я чего проглядел, но ИМХО, вместо jQuery можно было бы обойтись ведением min-width.
    А шЫштой осел — да забудем уже про него:-)

    1. gordi
      30 мая 2009 г. в 13:41 / ответ на коммент sordes

      …обойтись ведением min-width…

      А внимательнее пост прочитать?
      Речь-то совсем о другом :)

      1. sordes
        30 мая 2009 г. в 14:02 / ответ на коммент gordi

        Да, вроде, мысль понятна.

        1. 30 мая 2009 г. в 17:14 / ответ на коммент sordes

          Покажите тогда на примере, как то же самое будет решено на чистом CSS.

          1. sordes
            30 мая 2009 г. в 17:21 / ответ на коммент Dimox

            Посидел, покрутил, и понял, что при расширении контентной части без скриптов никуда.

          2. 8 июня 2009 г. в 22:15 / ответ на коммент Dimox

            C некоторыми оговорками (последняя строка ячеек всегда будет по горизонтальному центру, сколько бы их в строке не было) – можно:
            Для

            ul class="column"

            text-align:center

            , для списков – display:inline-block; без обтекания + хаки для IE и младших лисиц.

  2. gordi
    30 мая 2009 г. в 13:42

    Дима, кинул тебе на мыло, свою новую разработку,
    к ней поможешь свое хозяйство прикрутить?

  3. 30 мая 2009 г. в 17:19

    Пиши статью, но лучше, если за основу макет возьмешь стандартный трех колоночный.
    Пусть там и ширина колонок меняется и размер шрифта.

    Не понимаю, каким образом может пригодиться в трехколоночком макете техника динамических колонок. Именно в таком макете достаточно указания %-й ширины, ведь количечество столбцов в строку всегда будет одинаковое.

    А изменение размера шрифта к такому макету можно прикрутить.

    1. gordi
      30 мая 2009 г. в 17:40 / ответ на коммент Dimox

      Не понимаю…

      Нет, конечно, переноса колонок делать не надо :)
      Но динамика измения ширины колонок и одновременно размера шрифта нужна.
      Важны пропорции не только в ширине колонок , но и в расстоянии между ними.
      Приблизительно так, как в посланном тебе на мыло, моем макете,
      не важно, что там фиксированная колонка, в принципе все может прокручиваться.
      Причем, вместе с min/max-width всему макету.
      Пусть ширина колонок в %.
      Как пропорциональное именине размера шрифта к этому привязать?

  4. gordi
    31 мая 2009 г. в 13:05

    Спасибо, Дима за помощь.
    Все получил.
    Играюсь :)
    Если будут вопросы то задам, ты же автор данной фишки.
    Пиши статью, от себя обязательно линк дам,
    думаю многим пригодится.

    1. 31 мая 2009 г. в 17:19 / ответ на коммент gordi

      Пожалуйста. Статью напишу.

      1. gordi
        31 мая 2009 г. в 17:41 / ответ на коммент Dimox

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

        1. 1 июня 2009 г. в 08:38 / ответ на коммент gordi

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

  5. Далаирен
    30 июня 2009 г. в 11:35

    FF3 Win7RC1
    Скрипт, боюсь, не выполняет свою функцию.
    Opera10 Wnin7RC1 – нормально.

    1. Далаирен
      30 июня 2009 г. в 12:06 / ответ на коммент Далаирен

      Прошу прощения – деза)
      В примере не выполняется, но к кастому моему вполне прикрутилось. о_О
      Мистика.

  6. Ксаныч
    12 августа 2009 г. в 15:08

    Спасибо, очень интересный пример! Интересно и увлекательно разобран по полочкам. Что-то в этом роде я придумал на div, а на списках не догадался. Не додумался и картинкам назначать ширину width: 89% – клёво!
    Но вот вопрос: я решил этот пример использовать для фотоальбома, в котором фоты наложены “внавал”, резиново. Но к каждой фотке хотелось бы вставить комменты.
    Если размеры и ориентация, а также объем комментов строго одинаков, то все идет пучком: при изменении разрешения экрана, размера окна браузера все резиновое и “резинит” отлично.
    Но в реале фотки имеют разный размер и ориентацию, разный объем текста и колонки получаются разной высоты. И вот тут получается неприятный фикус-покус: маленькие колонки цепляются за высокий правый край бОльших колонок, находящихся раньше – получаются зияющие пустоты. Как их избежать – ума не приложу.
    Может честной изобретательный и остроумный народ подскажет что-то оч.ценное? Или такая идея неважнецкая?

  7. mag13
    12 сентября 2010 г. в 20:15

    а как закинуть шаблон в joomla?

  8. mag13
    12 сентября 2010 г. в 20:19

    А почему он не воспринимает русский шрифт?Как актуализировать русский шрифт ?

    1. 13 сентября 2010 г. в 08:58 / ответ на коммент mag13

      Видимо, сохраняете в неправильной кодировке.

  9. mag13
    13 сентября 2010 г. в 09:50

    Подскажите пожалуйста в какую кодировку написать и где, наверно В CSS. Очень надо

    1. 13 сентября 2010 г. в 10:59 / ответ на коммент mag13

      Во-первых, кодировка указывается в текстовом редакторе, в котором сохраняется файл.

      Во-вторых, она указывается в HTML-коде в теге <meta>, например:

      <meta http-equiv="content-type" content="text/html; charset=utf-8" />

      Здесь utf-8 – это название кодировки. Она должно быть одинаковой в обоих случаях. Можно также использовать кодировку windows-1252.

  10. mag13
    13 сентября 2010 г. в 11:40

    Спасибо Dimox, буду пробовать)

  11. mag13
    13 сентября 2010 г. в 12:17

    не получается( Dimox скажи пожалуйста как в кодировке демо сайта сделать так чтобы читался русский шрифт. Я поменял то, что ты говорил и в настройках блокнота по умолчанию задал данную кодировку (UTF-8), но ничего не помагает((

    1. 13 сентября 2010 г. в 12:56 / ответ на коммент mag13

      Замени iso-8859-1 на utf-8 и сохрани файл в utf-8.

  12. mag13
    13 сентября 2010 г. в 13:21

    Сработало!Большое спасибо Dimox. Очень помог частенько буду посещать этот сайт!

  13. крок
    27 апреля 2011 г. в 05:17

    Подскажите куда вставлять jQuery Сайт будет под Joomla Спасибо!

    1. 27 апреля 2011 г. в 10:18 / ответ на коммент крок

      Посмотрите, как сделано в примере, и сделайте по аналогии.

  14. 30 апреля 2011 г. в 14:24

    Каким образом в блоки картинки вставить? Спасибо!

  15. Алексей
    29 мая 2011 г. в 18:51

    как можно распределить свободное пространство между блоками!? Спасибо!

    1. Вопрос непонятен.

      1. у вас свободное пространство распределяется в блоки тем самым они растягиваються одинаково и заполняют всю страницу по ширене с фиксированными отступами между блоками.
        А как сделать так чтобы свободное пространство распределялось между блоками а сами блоки оставались с теми же размерами?

        1. Сходу я могу лишь сказать, что самое просто – сделать это таблицей. Вот пример:

          <table style="width:100%">
          	<tr>
          		<td style="width: 150px">123</td>
          		<td></td>
          		<td style="width: 150px">456</td>
          		<td></td>
          		<td style="width: 150px">789</td>
          	</tr>
          </table>
          
  16. 31 мая 2011 г. в 11:51

    а как сделать если сделано не в таблице каждый блок прописан в div для резиновой странички? Спасибо!

    1. Не знаю.

  17. Galina
    20 апреля 2012 г. в 12:01

    Добрый день,
    хорошая тема.

    1. В браузерах Opera и Firefox пример работает как задумано.

    2. В браузере IE приведенный пример не работает:
    – ширина колонок (div-ов) не изменяется при изменении ширины окна;
    – колонки (div-ы) ведут себя как div-ы со стилем float и поэтому справа всегда какое-то место остается. Div-ы не заполняют все пространство.
    – при уменьшении экрана до размера, на котором помещается 4 div-а IE входит в ступор – зацикливается. После этого его остается только закрыть.

    3. Напишите пожалуйста, не встречался ли в Вашей практике плагин или пример работающий на трех браузерах.

    Галина
    PS Ссылки на пример, переадресовываются и пример получить нельзя.

    1. 20 апреля 2012 г. в 14:44 / ответ на коммент Galina

      У меня работает во всех браузерах, в том числе и в IE, начиная с 6-й версии. Вот рабочий пример – http://fiddle.jshell.net/Dimox/U2A3j/1/show/light/

      1. Galina
        20 апреля 2012 г. в 17:58 / ответ на коммент Dimox

        http://fiddle.jshell.net/Dimox/U2A3j/1/show/light/

        Этот пример (у меня IE вер.9) работает на широком экране 1800 и при уменьшении окна до 5-6 колонок. Но нельзя уменьшить окно до одной колонки (до одного div-а).
        Нельзя преодолеть рубеж 4-5 колонок (div-ов) – IE зацикливается.
        В других браузерах этого не происходит.

        Попробуйте пожалуйста уменьшить окно до одной колонки, интересно что у Вас получится?

        Я выводила ширину окна в Вашем примере ив своем (с другими размерами div-а) и обнаружила, что Ваш и мрй пример зацикливают IE ровно при ширине окна 950px.
        Вам это что-нибудь говорит?

        Спасибо,
        Галина

        1. 20 апреля 2012 г. в 20:09 / ответ на коммент Galina

          У меня без проблем уменьшается до одной колонки.

          1. Galina
            21 апреля 2012 г. в 11:52 / ответ на коммент Dimox

            У меня все заработало после удаления, баров-надстроек в IE.

            Спасибо
            Галина

            1. 21 апреля 2012 г. в 12:58 / ответ на коммент Galina

              Замечательно.

  18. Алексей
    21 августа 2014 г. в 17:32

    А если задача немного иная? То есть, блоки расположены не слева-направо, а сверху-вниз, если объема хватает они стоят по одной вниз, если нет, выкидываются поочередно во второй вертикальный ряд.

  19. 7 сентября 2014 г. в 15:01

    Дмитрий, спасибо большое за инфу. Создал колонки с помощью вашего способа и скинул файлы html, css и js себе в папку-“заначку” . У меня уже коллекция заготовок с различными способами реализации “резины”. Если вас заинтересует, то есть еще один интересный способ реализации вашего примера html. Фактически берем за основу вашу разметку. Только в таблице стилей для списка (ul и li) прописываем свойства таблицы. Конкретно:

    ul { display: table-row; width: указываем нужную ширину;}

    ul li {display: table-cell;}

    .block {display: table-cell;
    width: указываем ширину ul. Благодаря этому все блоки равномерно распределяются по горизонтали;}

    Для родителя ul.column ( у вас его нет) прописываем max-width, min-width и нужные величины border-spacing (задает отступы между ячейками-колонками сверху и снизу.

    Это все. Прописал только те функции, на которых нужно акцентировать внимание. Все эти background и прочее указывается индивидуально.

    Преимущества этого способа:
    1) одинаковая высота и ширина всех колонок;
    2)в каждую колонку-ячейку можно ввести любой объем контента. Если это будет текст (разный объем в разных колонках), то при сужении экрана браузера колонки будут синхронно менять свой размер, подстраиваясь под самую большую;
    3) при сужении экрана текст, объем которого будет превышать размеры колонок, будет давить на нижнюю границу колонки, автоматически растягивая ее вниз.

    Этого невозможно добиться, если указать высоту колонки или ее родителя. У вас указана высота .block {height: 355px;}, поэтому при сужении экрана избыточный текст “проваливается” через нижние границы колонок. В моем случае колонки подчиняются закону таблицы и этого не происходит.

    Если данный метод пригодится вам или кому-то из посетителей вашего бога, то буду только рад…

  20. Дмитрий
    4 октября 2014 г. в 08:39

    А как разбить на колонки простой текст (с определённым кол-вом строк)? Это вообще возможно?

Ваш комментарий

Жирный текст

Ссылка

Цитата

Внутристрочный код

CSS-код

HTML-код

JavaScript-код

PHP-код