Скажем прощай oveflow: hidden!

Скажем прощай overflow: hidden!

Продолжу эстафету, начатую автором блога cuprum.name, в которой эстафетостартер ( :) предлагает блогерам поделиться со своими читателями переводом интересных зарубежных статей из своего RSS-ридера.

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

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

Из часто встречающихся решений для очистки плавающих блоков можно увидеть (кратко пройдёмся по всем методам):

1. Метод с дополнительным <div style="clear:both"></div>

Который (<div>) помещается в тот же контейнер, в котором есть плавающие блоки, непосредственно после них. Позволяет контролировать плавающие элементы относительно последующей разметки. Например, не позволит следующими за плавающей картинкой заголовкам, спискам, абзацам и т.д, наползать на неё.

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

2. Метод с position: relative

Позволяет «вернуть» высоту и видимость фона родительского блока, относительно плавающего, с помощью свойства position: relative.

Основная сложность метода в том, что такой подход трудно контролировать в сложной разметке, если родителей для элемента с float очень много. И для всех придется дополнительно прописывать CSS-свойство position: relative. Ест много времени верстальщика и требует усиленного тестирования. Поэтому, лучше сразу забыть про этот способ.

3. Метод overflow: hidden

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

Суть метода в том, что родителю плавающего блока добавляется свойство overflow: hidden. Преимущество в том, что по сравнению с предыдущим способом, можно вылечить поток всего лишь одной строкой.

Правда, требуется дополнительный «костыль» для IE6: дополнительно включаем hasLayout с помощью zoom: 1, или, если требуется валидность, height: 1%.

Весь код в этом случае выглядит примерно так:

1
2
3
4
5
6
#container {
    overflow: hidden;
}
* html #container {
    height:1%;
}

Несмотря на кажущуюся простоту, overflow: hidden иногда не годитcя, если в верстке нужно использовать элементы с отрицательным margin (попробуйте прицепить вебдванольный стикер в такой блок), есть проблемы с ссылками-якорями в Opera (об этом я расскажу в следующий раз), и способен преподнести сюрпризы, как в этом демо (два нижних примера).

Если есть ограничения, значит метод уже не универсальный.

4. Самоочистка для плавающих блоков

Давно известный (да, я не сделал громких откыртий в этом посте!), но мало распространённый метод, основанный на применении к плавающему блоку свойства content: after, выводящему дополнительный контент (текст, точка или пробел) после него, к которому применяется display: block, чтобы сделать его блочным элементом с очисткой clear: both, и одновременно невидимым с помощью visibility: hidden

В общем, лучше сразу смотрите код, который недавно обновился и больше не поддерживает устаревший IE/Mac:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.floatElement:after {
	visibility: hidden;
	display: block;
	clear: both;
	content: " ";
	height: 0;
}
/* хаки для IE6,7 */
* html .floatElement {
	height: 1%;
}
*:first-child+html .floatElement {
	min-height: 1px;
}

Судя по той же демке (пример 2), способ избавит вас (как минимум :) от проблем с тенью в CSS3.

Способ более универсальный и гибкий, по сравнению с первыми двумя, и позволяет избежать проблем, связанных с «обрезкой» overflow: hidden и просто просится занять свое место в вашем личном CSS-фреймворке. Кроме того, это единственный метод, который применяется непосредственно к плавающему элементу, а не к его родителю.

Лучше всего его использовать, создав отдельный класс в стилевом листе для плавающих элементов, как, например, .group в статье-источнике мыслей или книге Дэна Седерхольма «Handcrafted CSS».

Дополнительно про float можно почитать на designformasters.info

* * *

Участники эстафеты:

* * *

На этом всё, передаю эстафету Сергею М. (iskariot.ru), Виталию (codeisart.ru) и Насте (mannodesign.com).

Кроме того, чтобы эстафета получила активное развитие (или я кого-то забыл пригласить), предлагаю присоединиться, если вы ведёте блог на смежную тему, имеете в своем активе не ниже ста RSS-подписчиков и способны выполнить все условия эстафеты. Присоединяйтесь!

* * *

* * *

Понравилась статья?

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

* * *

Статьи по теме:

Комментариев: 16

  1. Dimox, 21.12.2009 в 13:56

    Я постоянно пользуюсь 1-м, 3-м и 4-м методами, в зависимости от конкретной ситуации.

    По поводу 3-го пункта, можно сделать просто вот так:

    1
    2
    3
    4
    
    #container {
        width: 100%;
        overflow: hidden;
    }

    тогда хак для IE6 не нужен.

    А про 2-й способ вообще первый раз вижу и не понимаю, что это за способ такой.

    Ответить

    • rotor, 21.12.2009 в 14:26

      Есть такой способ (второй), я помню давно вычитал на одном из англоязычных блогов. Но после нескольких попыток использования отказался в пользу третьего метода.

      А после прочтения книги «Пуленепробиваемый веб-дизайн» Седерхольма, года три назад, пользуюсь четвёртым.

      Ответить

  2. @ Never Lex, 21.12.2009 в 14:07

    Да. Решение отличное. Overflow:hidden тут вообще ни к селу ни к городу, имхо. Мне никогда не нравился. В основном юзал 1й и 4й методы.

    Ответить

    • rotor, 21.12.2009 в 14:30

      Я бы не стал так резко. overflow: hidden хорошо работает в простой вёрстке «без выкрутасов».

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

      Ответить

  3. @ Q-Zma, 21.12.2009 в 15:57

    Вместо вот этого:

    1
    2
    3
    4
    5
    6
    7
    
    /* хаки для IE6,7 */
    * html .floatElement {
    	height: 1%;
    }
    *:first-child+html .floatElement {
    	min-height: 1px;
    }

    обычно использую:

    1
    2
    3
    
    parentElement {
    	zoom:1;
    }

    в CSS, подключенном через conditional comments.

    Ответить

    • rotor, 21.12.2009 в 16:27

      Это понятно, но первый вариант, хоть и является хаком-костылём для IE, полностью валиден. Иногда (и для некоторых) это очень важно.

      Ответить

      • @ Q-Zma, 21.12.2009 в 17:27

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

        Ответить

  4. @ Cuprum, 21.12.2009 в 18:33

    К четвертому способу почему то была некая предубежденность; наверное, стоит начать использовать.

    Соглашусь с Q-Zma — сейчас оправданнее выносить весь мусор для IE 6 и 7 в условные комментарии (можно даже в один файл). У всех последних версий «смотрелок» все более-менее предсказуемо и им вполне может хватить одного стилевого файла.

    Ответить

  5. ioni, 22.12.2009 в 1:52

    Как на счет класса clearfloat?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    .clearfloat:after {
    	content:".";
    	display:block;
    	height:0;
    	clear:both;
    	visibility:hidden;
    }
    .clearfloat {
    	display:inline-block;
    }
    /* Hides from IE-mac \*/
    * html .clearfloat {height:1%;}
    *+html .clearfloat {height:1%;}
    .clearfloat {display:block;}

    Хотя у меня вообще это все идет обычно одной строчкой...

    Сильно напоминает третий вариант, с небольшими изменениями.

    Ответить

    • rotor, 22.12.2009 в 11:07

      Нет. Это, как раз-таки, и есть «старый» четвертый метод.

      Сейчас же он больше не поддерживает устаревший IE/Mac и убрали лишнюю «.» из контента (чтобы пользователи речевых браузеров не слышали после плавающих блоков что-то типа «интересный контент...точка...описание картинки...точка... »).

      Так что, в новых проектах, можно смело заменить этот код на тот, что представлен под номером 4 и снова быть на волне современных тенденций в верстке :)

      Ответить

  6. Ioni, 22.12.2009 в 16:54

    Век живи

    Ответить

  7. Max, 11.03.2010 в 14:29

    я использую первый метод, делаю такой div {clear: both; font-size: 1px; height: 10px;} и использую его, чтобы сделать отступы, а то, что надо лезть в хтмл меня не затрудняет.

    Ответить

  8. @ Maxim, 08.12.2010 в 13:17

    Есть способ, когда свойство content: after добавляется родителю плавающего блока:

    .container:after {

    display:block;

    clear:both;

    content:"";

    }

    /* Если нужно, для IE 6 включаем haslayout */

    * html .container {height:1%;}

    Эффект такой, как при первом способе, но не нужно «лезть» в HTML.

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

    Ответить

  9. @ Павел, 20.03.2011 в 1:04

    Я использую {display:inline-block} для родителя.

    По моему очень удобно, одна строчка и валидно. :)

    Ответить

  10. @ Apache, 08.05.2011 в 9:59

    В четвертом способе написано [b]"Кроме того, это единственный метод, который применяется непосредственно к плавающему элементу, а не к его родителю.[/b]" Кажется это ошибочно, судя по всему 4-й способ все таки применяется к родительскому блоку содержащему плавающие элементы.

    [b]css:[/b]

    [code]

    .floatElement:after {

    visibility: hidden;

    display: block;

    clear: both;

    content: " ";

    height: 0;

    }

    /* хаки для IE6,7 */

    * html .floatElement {

    height: 1%;

    }

    *:first-child+html .floatElement {

    min-height: 1px;

    }

    ul.test {

    padding: 5px;

    border: 1px solid red;

    }

    ul.test > li {

    margin: 5px;

    width: 25px;

    height: 25px;

    background: blue;

    float: left;

    }

    [/code]

    [b]html: (не работает)[/b]

    [code]

    [/code]

    [b]html: (работает)[/b]

    [code]

    [/code]

    Ответить

Есть что сказать?