Равноудаленные блоки и :first-child

31 января 2010 года | Вёрстка

В этот раз хотелось написать, что-то о вёрстке. Сначала хотелось взять и рассказать о чем-то новом, например о CSS3, но передумал. А начать я решил с небольших полезностей, которые часто использую сам в верстке.

В этот раз хочу рассказать о удобстве использования псевдо-класса :first-child.

Представим, что у нас есть главный блок фиксированной ширины, и в нём нужно разместить несколько элементов (также блоков), которые «прилипают» к левому и правому краю «родителя». И при этом имеют между собой равный отступ. Но на словах это сложно представить, поэтому я изобразил всё ниже на рисунке.

css blocks
А вот и сам HTML:

<div id="wrapper">
    <div class="section">Блок 1</div>
    <div class="section">Блок 2</div>
    <div class="section">Блок 3</div>
</div>

Чтобы растянуть на всю ширину три блока внутри родительского, мы применим несколько строчек CSS кода. Первая мысль, что приходит в голову, это указать классу .section, ширину и нужный отступ справа. Но возникает проблема с последним крайним блоком. Его отступ будет больше ширины родительского блока.

css wrapper section margin-right
Так как третий блок, из-за отступа не влазит в ширину родительского элемента, то и браузеры его будут «сбрасывать» ниже:

css section block
В итоге, последний <div> будет перемещен вниз, и возникает вопрос, как задать последнему элементу отступ равный 0 (нулю).

Как я уже и сказал в начале статьи, что для решения этой проблемы можно применить удобный селектор :first-child, А также сменить правый отступ в дочерних блоках на левый. Получится, что теперь проблема у самого левого блока, а его легко может обработать наш псевдо-класс.

Итак, при написание стилей, сразу оформим родительский блок:

#wrapper {
    width: 320px;
    height: 60px;
    background: #EFEFEF;
}

За ним опишем класс для всех внутренних блоков:

.section {
    border: solid 1px #999;
    float: left;
    height: 58px;
    margin-left: 10px;
    width: 98px;
}

В этом примере, я использовал фиксированную ширину и отступ. Но если вам нужно задать динамическую ширину, можете указать значения например в процентах.

Теперь мы удалим отступ у первого внутреннего блока:

#wrapper div:first-child {
    margin-left: 0px;
}

Как браузеры понимают этот псевдо-класс? Сначала находится элемент с id=»wrapper», а затем первому дочернему элементу применяет этот стиль.

В итоге получаем:
css :first-child

Вот такое не хитрое и удобное использование этого селектора.

Этот пример работает прекрасно в любом современном браузере. А так как я не считаю IE6 современным браузером, к нему это не относится.

Но проекты бывают разные и заказчики бывают разные. Поэтому, дам совет, как исправить данный пример, чтобы он корректно работал и в IE6.
Нужно для первого дочернего элемента использовать другой класс, например .section-first или добавить второй класс .section.first и прописать для него нулевой отступ.

  • http://rendermarket.com Сергей

    Отличная тема, теперь буду пробовать делать так, а то мы с тобой недавно обсуждали подобное :)

    Кстати а как файрфокс2 относится к этому?

  • divbyzero

    Для IE7, Firefox 2, Safari 3.0 не сработает, если только элементы добавлены динамически (через яваскрипт). В остальных случаях проблем нет.

    Так что смело можно написать что есть поддержка:
    IE7+, FF2+, Safari 3.0+, Chrome 1+, Opera 9.62+, Konqueror 3.5.7+

  • http://rendermarket.com Сергей

    Хром этот еще – очередная головная боль на головы верстальщиков

  • divbyzero

    Так как браузер (Chrome) активно развивается, с ним я думаю проблем будет всегда меньше, чем с например тем же IE.

  • http://www.nayjest.ru/ Master Nayjest

    Я конечно уважаю и признаю div’ную верстку, но такие вещи всегда делал таблицей и это правильно, я считаю.

    Если речь не идет об основных колонках сайта, каркас сайта таблицей — это чаще всего моветон, да.

  • http://www.nayjest.ru/ Nayjest, web-developer

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

    Проблемы у меня почему-то всегда возникают в Опере (ну ИЕ — понятно, да, бороться с ним уже рука набита, хотя с тремя версиями теперь стало значительно сложнее, а вот Опера иногда выдает тааакую хрень, особенно старенькие версии, был у меня один заказчик с оперой восьмой, так я думал — чокнусь, пока сверстаю под нее нормально, хотя там проблемы больше были в жабаскрипте, чем в верстке).

  • divbyzero

    Согласен, Опера ниже 9.62 вообще сплошной неадекват.

    В любом случае, новый популярный браузер, это больше работы верстальщикам.

  • http://medialworld.com sad

    О_о таблицами? Жесть. Рисовать таблицу из-за трех простых блоков? Таблицы нужны для табличных данных. А в этом примере явно три разных блока и на таблицу не похоже.

  • http://medialworld.com sad

    >> «Но проекты бывают разные и заказчики бывают разные. Поэтому, дам совет, как исправить данный пример, чтобы он корректно работал и в IE6.
    Нужно для первого дочернего элемента использовать другой класс, например .section-first или добавить второй класс .section.first и прописать для него нулевой отступ.»

    В целях совместимости только так и стоит поступать (если кнешно вы на совместимость болт с левой резьбой не ложили). Так что, нафиг эти псевдо-классы (покрайней мере пока существует еще ИЕ6) и юзайте другие классы. Кода добавиться всего два слова, но совместимость будет стопроцентная.

  • divbyzero

    Хочу заметить, как вот недавно узнал, IE6 очень плохо понимает несколько классов (.class1.class2 не работает).
    Поэтому нужно для IE6 совместимости, указывать совсем другой класс.

  • http://medialworld.com sad

    Хм… не замечал за ИЕ6 такой фигни. Наверное потому, что редко использую несколько классов.

  • divbyzero

    Сам был удивлён.
    Но для этого даже создал несколько примеров и протестировал. Да, IE6 игнорирует второй стиль.
    Наверное, это тема для ещё одной статью-заметки про IE6.

  • Selenit

    Имхо, c таким распределением блоков надежнее справляется text-align:justify (сами блоки при этом должны быть строчными — inline-block). Такой подход не зависит от ширины блоков и контейнера. Есть несколько подводных камней (в старых IE и, как ни странно, Webkit-е), но они несложно обходятся (http://forum.htmlbook.ru/index.php?showtopic=20735).

  • abc_ua

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