Верстка повторяющихся блоков

    Довольно часто при верстке сайта возникает необходимость размещать блоки одинаковой ширины, но разной высоты в контейнере с переменной шириной (читай резиновом). Плюс на этот список может применяться фильтр, который JS-ом скрывает или показывает элементы списка, при этом он не должен разрушать «строки», верстку, или образовывать дыры, поэтому решения на таблицах не катят сразу. Простейший пример — каталог товаров:



    Решили вместе с morfi сделать более-менее универсальное решение, которое бы позволило без лишних проблем публиковать такого рода контент. Важный момент — что высота блоков может зависить, к примеру, от высоты заголовка, или от описания, если бы оно было в макете.

    Тут есть два подводных камня. Первый — зазоры между блоками. Если просто поставить float:left; margin-right|bottom:50px (я упростил синтаксис), то у последнего элемента в «строке» всегда будет отступ, поэтому он никогда не будет четко на границе контейнера.

    Решение с float, лежащее на поверхности:

    1. Элементам задаем float:left; margin-top|left:50px
    2. Заворачиваем элементы в ещё один контейнер и ему задаем margin-top|left:-50px — отрицательный отступ, и пусть теперь внешний контейнер (изначальный) будет называться wrapper, а внутренний — container.
    3. Контейнеру и врапперу для дружбы с IE нужно присвоить zoom:1 и чтоб они не схлопнулись от float-элементов — overflow:hidden
    4. Чисто для IE нужно указать display:inline для блоков, иначе мы получим удвоенный margin

    Все бы ничего, но в такой ситуации, если высота блоков может сильно отличаться, может возникнуть вот такой косяк:



    Обратите внимание на блоки three, four и five. Зеленый блок — это враппер, синий — контейнер.

    Логически ситуация понятна — блок должен тянуть линию (или «строку»), в которой он находится. Это поведение — типичное для display:inline-block.

    Для того, чтобы применить это решение на практике нужно:

    1. Снова задаем margin как и в примере выше
    2. Блокам раздаем универсальную кроссбраузерную конструкцию display:-moz-inline-box; display:inline-block; *zoom:1; *display:inline
    3. Замечаем, что горизонтальные расстояния оказались чуть больше нужных 50px — это из-за пробелов, затесавшихся между inline-block
    4. Для борьбы с пробелами измеряем его ширину — получается 4px, а это 25% от 1em, который по-умолчанию равен 16px. Таким образом контейнеру ставим word-spacing:-0.25em, а блокам word-spacing:normal
    5. Для IE нужно также прописать блокам text-align:top, иначе элементы будут выровнены по базовой линии.



    Багов пока не замечено, решение кроссбраузерное. Inline-метод спокойно выдерживает простановку text-align:center у контейнера (см. скриншот). Надо только не забыть у блоков выставить обратно text-align:left (см style.css — я их закоментировал там).

    Работающий пример доступен по адресу: http://test.dis.dj/blocks/.

    P. S. Решение не ново, но оно будет полезно в любом случае.

    P. P. S. На скриншоте — будущий интернет-магазин-портал для мамочек.
    Share post

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 63

      +6
      Это разве что относится к элементам с текстовым описанием товара, но его ведь можно не весь показывать а обрезать в конце overflow:hidden (+ затенение сделать).

      Такие прыгающие блоки мне кажется не красиво смотрятся. Хотя задачи разные бывают.
        +2
        Предполагается, что описание везде более-менее одинаковое ±20…30 пикселей, как на скриншоте сайта (если бы там было название в две строки). Резать — не очень хорошо, т.к. в самом низу очень важная кнопка «купить», она обязательно должна отображаться.
          0
          Блок разделить на логические части: Название, картинка, описание, цена, купить (порядок по усмотрению). Каждому блоку дать свое расположение и размеры.
          Название — максимум 2 строки (обычно хватает), картинка везде одинакового размера (ресайз для всех одинаков), описание режем overflow, цена одной строкой, купить тоже одной строкой.

          Если описание и название нужно более информативное, то картинку и описание ставить по бокам.

          ИМХО одинаковыми блоками товыры смотрятся более привлекательно.
            +4
            Вы клиенту попробуйте объяснить, что называть товары можно только короткими строками. Лучше использовать универсальное решение. Тем более, что оно даже без костылей.
          +2
          Так они прыгают только при ресайзе. Вы не так часто его делаете на одной странице.
            +2
            Мы не так часто, а Вы не замечали, как работают различные менеджеры, секретарши и прочий гуманитарный народ? Они порой такое вытворяют, что никогда бы не подумал сам это сделать… Вот для них мы и делаем такие сайты… где предусмотрена каждая мелочь!

            Лично мне так вообще всех этих дизайнов и украшательств не надо… Это надо для клиента… и клиентов клиента!
              –3
              И это самое гнусное что секретарша проверяет вашу работу которую вы делали для посетителей сайта, а не конкретно для нее с ее монитором.
                +1
                Вы не правильно поняли… Секретарша мою работу не проверяет, она ей пользуется… =))

                Да и не вижу ничего гнусного в том, чтобы попросить секретаршу потестировать юзабилити сайта… но это уже скорее вопросы к дизайнеру, а не к программисту или верстаку!

                И почему мы должны делать работу конкретно для неё и её монитора??
                  –2
                  В некоторых «компаниях» сайтом занимаются секретарши.
                  +3
                  обычно, те самые секретарши находят довольно забавные баги. причем там куда, или где, «нормальные» люди бы никогда не тыкнули
                    0
                    Во время тестирования надо «тыкать» везде, куда руки дотянутся :)
              0
              да, вот если бы у них еще фон тянулся без всяких table-cell…
                0
                Да, в данный момент как раз над этим и размышляю. Кроссбраузерно сделать будет похоже непросто — я помню, насколько тяжелое решение для двух-то колонок chikuyonok.ru/2009/06/float-columns/ и habrahabr.ru/blogs/webdev/62205/
                  0
                  тут не просто 2 колонки, а еще возможность пустой ячейки. я что то вообще не вижу способа, если честно :-(
              –1

              Mozilla/5.0 (Windows; U; Windows NT 6.0; ru-RU; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4 (.NET CLR 3.5.30729)
                +2
                Это Вы пример на float смотрите. Он как раз иллюстрирует как не надо.
                  0
                  ааа, я просто думал у вас два нормальных решения, на флоатах и инлайнах
                +1
                Я думаю, что это хорошее решение. Мне сейчас как раз предстоит верстка подобного макета, и я воспользуюсь этим методом.

                Сейчас сделал всё на float:left, но это меня не очень устраивает, т.к. макет 3х колоночный и такие плавающие блоки в нем подглючивают.

                Это решение, которое предложил dfuse мне очень подходит, чего и всем желаю. Правда подобный вариант я видел и у Артемки Лебедева. Но там немного иначе все.

                Молодец, dfuse, спасибо за пост!
                  +1
                  Распашенка металлическая порадовала.
                    0
                    Хорошее, годное решение для выкладки товаров и подразделов с непредсказуемыми описаниями/сниппетами.
                      +1
                      Затем и создавалось :)
                      +2
                      Там еще vertical-align:top; есть, без которого, всё будет не так «красиво»
                        +1
                        Спасибо что напомнили, забыл этот момент упомянуть. В комментариях в CSS про это есть.
                        0
                        всё гениально просто ;)
                        deer.org.ua/2009/08/25/1/
                          –1
                          И да, картинка первая — больше для привлечения внимания %)
                            0
                            Нет, это реальный сайт. Для него и делали собственно :)
                              0
                              нужно было бы подобрать с разношерстным контентом, вот! Что бы было понятно
                                0
                                Сайт еще в разработке… там контента еще не так много, чтоб было из чего выбирать :(
                                  0
                                  «рыба» наше всё ;)
                            +2
                            Ну дык :) одним и тем же инструментарием пользуемся :)

                            margin: 0 24px 20px 0­; — я смотрю Вы решили с пробелами не заморачиваться ))) те же 4 пикселя
                              +1
                              Гармония главнее %)
                            +2
                            Вот так натыкаешься на статью иногда и оказывается, что у меня были распашОнки, а у кого-то будут распашЕнки :)
                            Спасибо за решение :) Ушел переверстывать два макета.
                              +3
                              чОрт :)))
                                +1
                                да лан переверстывать — 2 свойства поменять и псевдоэлементы, что поток очищают после каждого ряда стереть
                                  0
                                  Хотела обратить внимание на эту ошибку, но вы успели раньше :)
                                  На скриншоте какие-то сплошные «РаспАшенки», чего они там пахать должны, непонятна.

                                  У Артемия Лебедева на сайте есть какое-то решение горизонтального выравнивания блоков разной высоты.
                                  0
                                  Хм. Странно: в фф3.6 блоки перемещаются между строчками только когда отпускаешь кнопку мыши. Это так и задумано? Потому что, например, решение с версткой на таблицах дает результат ресайза сразу (тут, естественно, не получится джае перемещать элементы между строчками).
                                  Кстати, не знаете, как подобные вещи сделаны, например, утЯндекса в Фотках?
                                    0
                                    Хм, в остальных браузерах всё сразу.
                                      +1
                                      Извините. Обознался. Был не прав.
                                      В общем, если ресайзить окошко средствами винды, то браузер видимо ждет отжатия кнопки.
                                      Если ресайзить за правый нижний угол, то все хорошо.
                                    0
                                    ух! спасибо, буду использовать
                                    а то от нехватки смекалки юзал overflow:hidden
                                    • UFO just landed and posted this here
                                        0
                                        А прикиньте, что будет, если элементов 100 штук, плюс растяг, плюс фильтр :) каждый раз перестраивать JSом? Нет, я лучше вот как здесь :)
                                          0
                                          если элементов будет 100 штук то лучше всё таки выводить постранично
                                          да я давно использую этот метод
                                            0
                                            насчёт таблиц и js
                                            images.yandex.ru
                                              0
                                              То, что я увидел на сайте яндекса — не совсем то, что в примере. Там полоска одна, а в примере их много, и элементы могут перемещаться по разным «строкам» при растяге.
                                                  0
                                                  nova.rambler.ru/pictures?query=css У каждого свой путь :)

                                                  Мне кажется, решение без JS лучше.
                                                    0
                                                    на яндексе оно ещё и тянется, а на рамблере просто прыгает.

                                                    Влюбом случае с js можно организовать красивее. при inline-block можно выставить ширину блоков в процентах и менять её в зависимости от ширины обёртки.
                                          0
                                          Для борьбы с пробелами измеряем его ширину — получается 4px, а это 25% от 1em, который по-умолчанию равен 16px. Таким образом контейнеру ставим word-spacing:-0.25em, а блокам word-spacing:normal

                                          А не проще задать font-size:0 для общего контейнера потока? Тогда пробелы даже если они просто станут не видны
                                            0
                                            Это, конечно, способ, но фишка в том, что word-spacing можно вернуть к нормальному просто присвоив normal, а вот размер шрифта обратно восстановить не получится, а он должен наследоваться прозрачно.
                                            0
                                            выложите полный код примера у себя! пожалуйста
                                              0
                                              Я Вас не совсем понял — пример test.nimax.ru/blocks/ чем не устраивает? Насчет полноты — все файлы доступны, все можно посмотреть. Там CSS вполне прозрачно подключен.
                                                0
                                                Для Firefox есть отличные дополнения для получения/изучения такого рода инфы:
                                                Web Developer, ну и обязательно для дева — FireBug.
                                                0
                                                Не в тему, но про войну. А для чего врапперы делаются? Часто их замечаю но не вижу практического смысла. Расскажите, а?
                                                  0
                                                  Ну например, чтобы сделать паддинг в блоке, при этом не раскукожив макет. То есть если у вас блок шириной 200 пикселей и ему надо задать паддинг по 20 пикселей с краев, то блок станет занимать 240 пикселей. Для этого в блок вкладывается еще один блок, и уже ему прописываются паддинги.
                                                    0
                                                    круто :) я прозрел :)
                                                    0
                                                    В данном случае — есть внешний div, которому придается все оформление целого блока — padding и все прочее, а также overflow:hidden, чтобы ничего наружу не торчало. Есть внутренний div, которому дается отрицательный margin, чтобы компенсировать зазоры между блоками. У самих блоков зазор выставлен через margin.
                                                    0
                                                    По опыту использования такого способа, word-spacing должен быть -0.3em, а не 0.25, а с переходом на мак обнаружил что для сафари нужен и того -0.35 (к счастью, 0.35 не портит картину в остальных браузерах, поэтому можно обойтись без хаков и сразу задавать нужное значение).
                                                      0
                                                      Ок, проверяем. test.nimax.ru/blocks/em.html — будет несколько алертов, «размер шрифта — размер пробела», рекомендую заглянуть в код — там все говорит за себя. Если что-то будет не так — сообщите, но у меня ровно четверть.
                                                      0
                                                      если говорить с точки зрения визуального восприятия, то выглядит это отвратительно. на мой взгляд гораздо лучше будет зафиксировать высоту блоков и напрячь программистов, чтобы те сделали обрезание текста.
                                                        +1
                                                        Если Вы смотрите на примеры — там специально такие дыры, чтобы наглядно показать суть проблемы. Предполагается, что больше чем на 50 пикселей плашки товаров отличаться не будут. А что касается обрезания — это самый топорный способ, и он совершенно никуда не годится.

                                                        Попробуйте потом объяснить клиенту, почему у него при вводе названия на 2 строки пропала ссылка «купить». Нельзя ничего обрезать — нужна гибкость.

                                                      Only users with full accounts can post comments. Log in, please.