Все, что вам известно о clearfix — неверно.

Перевод статьи:  Everything you Know about Clearfix is Wrong.
Автор:  Thierry Koblentz.

Что такое clearfix?

Clearfix — это основанный на CSS прием, который используется для решения проблем, возникающих при содержании «плавающих» элементов в рамках блока контейнера, не предусматривающий внесение каких-либо изменений в разметку документа.

Как это работает?

Вот что делает clearfix:

  • В браузерах, поддерживающих псевдоэлемент :after данный хак генерирует контент (находящийся сразу же за содержимым форматируемого элемента), которому назначаются CSS свойства, отменяющие обтекание плавающих дочерних элементов. Короче говоря, это дает примерно тот же эффект, что и включение структурного элемента <div style="clear:both"></div> непосредственно перед закрывающим тегом элемента.
  • В IE элементу назначается свойство hasLayout, в результате чего форматируемый элемент образует новый контекст блочного форматирования, включающий плавающие объекты (об этом ниже).

В результате имеем.

Из последнего пункта следует то, что в IE, и только в IE, хак clearfix создаст иную конструкцию. Это связано с тем, что контекст блочного форматирования:

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

Отрицательные стороны.

Все напрямую зависит от компоновки вашего документа и стилизации его элементов. Поэтому результаты применения хака clearfix могут быть непредсказуемыми. К примеру, на этом простом демо (иллюстрирующем случаи, упомянутые в первых двух пунктах предыдущего списка) можно увидеть различия визуализации в IE и в, так называемых, современных браузерах:

  • В Mozilla, WebKit, и т.д. :
    • Имеющиеся на странице три заголовка расположены на разных уровнях по вертикали.
    • Высота зазора сверху контейнера .wrapper (который содержит фоновое изображение) превышает 20px.
    • Плавающий блок .floatMe отображается за пределами контейнера wrapper.
  • В IE:
    • Все три заголовка выровнены по вертикали.
    • Высота зазора над контейнером .wrapper, составляет половину той, которая имеет место в современных браузерах.
    • Плавающий блок размещен в рамках элемента контейнера.

Что это дает?

Все эти различия объясняются очень просто:

  • В IE:
    • Блоку .wrapper назначено свойство hasLayout (так как он имеет фиксированное значение свойства width), поэтому он образует новый контекст блочного форматирования. Это предотвращает схлопывание поля элемента параграфа (черный блок) и поля заголовка, находящегося в элементе контейнере. Иначе говоря, верхний зазор – это нижнее поле margin-bottom черного блока (элемента <p>).
    • Плавающий блок находится в контейнере .wrapper, так как согласно спецификации, блочный контекст форматирования обязан включать все внутренние смещенные элементы (т.е. floats).
  • В современных браузерах:
    • Все присутствующие элементы находятся в одном контексте блочного форматирования, поэтому прилегающие поля (margins) объединяются. Поле внутреннего заголовка выходит за пределы контейнера .wrapper и упирается в край элемента параграфа <p>. В отличие от того что происходит в IE, здесь верхний зазор между контейнером и черным блоком образуется не нижним полем (margin-bottom) параграфа, а верхним полем (margin-top) заголовка.
    • По этой же причине плавающий .floatMe блок не находится в рамках родительского элемента .wrapper.

В данной ситуации мы не имеем дело с никаким багом. А причиной разногласий визуализации в IE и современных браузерах является тот факт, что мы просто применяем различное стилевое форматирование элемента .wrapper в рамках нашего тестового макета.

Теперь взгляните на второй вариант демо страницы, где блок .wrapper образует новый контекст блочного форматирования как в IE, так и в других браузерах. В общем, все выглядит намного лучше (да, в IE внизу плавающего блока присутствует зазор, что является багом, обусловленным тем, что для .wrapper установлено свойство hasLayout).

Как это связано с clearfix.

Давайте предположим, что мы недостаточно знакомы с таким понятием как блочный контекст форматирования и вместо того, чтобы назначить необходимые свойства стилей блоку контейнеру .wrapper, как мы это делали на предыдущем шаге, мы просто применим clearfix к диву <div>, содержащему плавающий элемент .floatMe.

Во время написания данного материала я пытался предположить, сможете ли вы самостоятельно предугадать изменения, которые будут вызваны применением хака clearfix, в рассматриваемом нами макете. Как бы там ни было, результат использования clearfix продемонстрирован на следующей демо странице.

Что же произошло?

Плавающий блок .floatMe включен, но в IE макет страницы нарушен, а именно – средняя колонка смещена вниз относительно боковых колонок. Это произошло потому, что согласно пункту 9.5 спецификации, контекст блочного форматирования не должен перекрывать плавающие элементы, находящиеся с ним в одном блочном контексте форматирования (как было указано выше в третьем пункте).

Теперь элемент, реализующий среднюю колонку .mainContent получил hasLayout (благодаря применению к нему хака clearfix>), в результате чего он создает новый контекст блочного форматирования, который уже не вмещается в пространство между двумя боковыми колонками и по этой причине смещается вниз.

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

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

Как можно исправить ситуацию.

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

Применяя необходимые стили для обеих элементов – контейнера .wrapper и средней колонки .mainContent, создающие блочный контекст форматирования (к примеру, для .wrapper определить display:inline-block а для .mainContent установить свойство overflow:hidden) вы решите проблему. В этом можно убедиться, взглянув на последний вариант нашего примера.

Подытожим все вышесказанное.

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

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

Это, конечно же, не означает что мы должны совсем отказаться от использования clearfix. Этот хак является отличным инструментом и вполне безопасен, при условии, что мы знакомы с нюансами его использования для содержания плавающих объектов. Кроме того, он может предотвратить объединение полей и «ускользнуть» от окружающих плавающих блоков в IE.

Я сам применяю clearfix для форматирования модальных окон и других подобных им элементов, точно зная, что в текущем контексте блочного форматирования нет плавающих элементов. Более того, я с уверенностью использовал его при создании своего фреймворка.

В данной статье под термином IE подразумевается IE 5, 6 и 7-й версий.
* Примечание переводчика.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *