Проблемы float и их решения
В процессе верстки с использованием float-элементов вы непременно заметите некоторые странности в их поведении. Мы расскажем о наиболее часто встречающихся проблемах и способах их решения.
Проблема 1. Обтекание влияет на другие элементы
На первом уроке по свойству float мы рассмотрели пример, где футер, расположенный сразу за плавающими блоками, ведет себя странно, прижимаясь верхним краем к низу float-элемента. Это происходит из-за того, что, по сути, футер обтекает боковую панель, но поскольку он занимает 100% ширины, то обтекание выражается лишь прижиманием к нижнему краю, без перемещения по горизонтали.
На примере ниже более явно показано, что происходит с элементом, который должен обтекать соседний элемент, но при этом им не хватает места в одном ряду:
Элемент с классом .b4
пробует обтекать float-элемент .b3
, содержащийся в контейнере .wrapper
, но поскольку .b4
не влазит в один ряд с .wrapper
, он просто прижимается верхней стороной к этому ряду, из-за чего между блоками не остается свободного пространства. Как видите, элементу .b4
дополнительно задано свойство margin-top: 50px
, эффект которого сейчас не заметен. Не зная причины, можно долго ломать голову, почему margin не работает. Однако, если посмотреть на элемент через инспектор кода, можно увидеть, что margin-top всё же работает, просто сейчас он никак не влияет на картину.
Как сделать, чтобы элемент .b4
перестал обтекать соседний? Конечно же, с помощью свойства clear
, которое мы уже рассматривали ранее. Повторим еще раз:
.b4 { clear: both; }
Добавив этот код, мы получили такую картину:
Уже лучше, но отступ в 50 пикселей сверху так и не появился. Он всё ещё накладывается на верхний блок:
Такое впечатление, что элементу со свойством margin-top
нет от чего отталкиваться. На самом деле, так и есть, потому что если мы проинспектируем элемент .wrapper
, то увидим, что его высота странным образом стала равна нулю:
Проблема 2. Нулевая высота контейнера с float-элементами
Еще одна проблема при работе с float-элементами заключается в том, что блок, содержащий плавающие элементы, теряет свою высоту, поскольку свойство float
исключает элементы из нормального потока. Высота родительского контейнера изменяется следующим образом:
- Если в контейнере содержатся только плавающие элементы, то его высота станет нулевой. Либо, если родителю задано, к примеру, свойство
padding-top
и/илиpadding-bottom
, то его высота будет равна сумме этих padding-ов. - Если в родительском контейнере помимо float-элементов имеются также обычные элементы, то высота родителя будет равна высоте этих обычных элементов плюс отступы.
Иными словами, из высоты блока-родителя просто вычитается высота float-элементов.
Как заставить родительский контейнер учитывать высоту содержащихся в нем плавающих элементов? Есть несколько способов решения этой проблемы. Мы расскажем о двух наиболее распространенных и эффективных хаках:
-
Micro Clearfix. Этот хак был придуман разработчиком по имени Nicolas Gallagher, и заключается он в добавлении нескольких строк CSS к псевдоэлементу
:after
родительского контейнера, потерявшего высоту:.wrapper:after { content: " "; display: table; clear: both; }
Этот код работает во всех современных браузерах. Преимущество данного способа состоит в отсутствии необходимости писать лишний HTML-код.
-
Overflow: hidden. Второй вариант решения проблемы с пропавшей высотой контейнера — добавить к этому блоку свойство
overflow: hidden
. Вообще, данное свойство определяет, будет ли видно содержание блочного элемента, если оно не помещается в него целиком и выходит за пределы области. Однако в данном случае оно еще и заставляет учитывать высоту float-элементов..wrapper { overflow: hidden; }
У этого метода есть недостаток: если в контейнере находятся абсолютно позиционированные элементы, размещенные за пределами его границ, то они могут исчезнуть из поля зрения. Впрочем, то же самое произойдет с любым содержимым, которое будет вылезать за область контейнера — такова работа значения hidden.
Итак, воспользуемся первым хаком и взглянем на результат:
Как видим, высота блока-родителя стала включать в себя плавающие элементы, а у элемента .b4
теперь нормально отображается верхний отступ в 50 пикселей.
Проблема 3. Перенос блоков при добавлении отступов
После создания колонок с помощью float
вы наверняка захотите наполнить их содержимым. В нашем примере есть три колонки одинаковой ширины, которые идеально помещаются в один ряд. Давайте добавим немного контента в каждую из них:
Выглядит неплохо, но нам не хочется, чтобы текст примыкал так сильно к боковым сторонам блоков. Чтобы сделать небольшие промежутки между текстом и внутренними границами блока, мы добавим padding
слева и справа (сейчас он добавлен только сверху и снизу в размере 40 пикселей, а для боковых сторон указан 0):
И здесь у нас появляется проблема: одна из колонок съехала вниз. Это случилось из-за того, что ширина каждой колонки стала равна не 33.333333%
, а 33.333333% + 10px + 10px. Как вы помните из предыдущего раздела учебника, полная ширина блока — это сумма чисел, в которую включена ширина содержимого, а также размеры боковых отступов, границ и полей.
Чтобы исправить эту проблему, используйте свойство box-sizing со значением border-box
. Тогда браузер будет автоматически включать отступы, поля и рамку в заданную вами ширину блока:
Рекомендуем при создании сетки в CSS заблаговременно прописывать box-sizing
, чтобы застраховаться от выпадания блоков при дальнейшей работе с сеткой.
Таковы основные проблемы, которые встречаются у float-элементов и могут быть легко решены. Безусловно, существуют и другие трудности, и некоторые из них порой нельзя обойти простым способом. Однако, зная принципы работы float и помня о вышеперечисленных недостатках, вы уже сэкономите много времени и нервов во время верстки.
Далее в учебнике: что такое адаптивный веб-дизайн.