Float и clear в CSS — инструменты блочной верстки

17 Март, 2012

Здравствуйте, уважаемые читатели блога KtoNaNovenkogo.ru. Сегодня мы продолжаем изучать классический CSS и на очереди у нас плавающие элементы, создаваемые с помощью Float. Так же мы затронем предназначение правила Clear (both, left, right) и посмотрим на примерах горизонтального меню и трехколоночного макета, как все это можно использовать на практике.

Чуть ранее мы с вами уже рассмотрели многие аспекты языка стилевой разметки, о которых вы можете узнать из составляемого по ходу повествования Справочника CSS. Таблицы каскадных стилей изучать значительно сложнее, чем чистый Html, и если вам что-то покажется сложным и на первых порах не понятным, то ничего странного и страшного тут нет. Попробуете на практике, набьете руку и все устаканится. Удачи!

Float — создание плавающих элементов в CSS коде


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

Но в CSS имеются два правила, которые могут это изменить. Речь идет о float и position. Когда к тэгам не применяются эти два правила, то такой вариант называется кодом в нормальном потоке.

С помощью float мы создаем так называемые плавающие элементы. Кстати, даже в чистом Html мы уже с вами сталкивались с подобным, когда для картинок прописывали атрибут Align со значениями Left или Right (читайте про обтекание картинок текстом и тег Img).

У этого правила имеется три возможных значения (по спецификации консорциума W3C), причем по умолчанию используется значение None, т.е. изначально у нас никаких плавающих элементов нет:

Значения Left и Right как раз и позволяют создавать плавание. При этом свойства такого тега поменяются и он иначе будет взаимодействовать с другими. Давайте рассмотрим все это на примере. Возьмем один строчный тэг Span и два блочных элемента Div.

Помните, в статье про назначение height и width я говорил, что для строчных элементов эти правила работать не будут, т.е. для них нельзя задать высоту и ширину. Поэтому для демонстрации изменения свойств плавающего элемента я добавляю строчному тегу Span правила height и width, которые в обычной ситуации работать, естественно, не будут.

Все правила я буду прописывать с помощью атрибута Styleпрофессиональной верстке этот способ практически не используется), о котором вы сможете прочитать по приведенной ссылке. Также для наглядности я подсвечу тэги фоном с помощью правила background:

<span style="background:#FFC0C0;height:30px;width:250px;">Строчный</span>
<div style="background:#C0FFC0;">Блочный</div>
<div style="background:#C0FFC0;">Блочный</div>

Теперь давайте пропишем для Span правило float со значение Left и посмотрим что из этого выйдет (для наглядности еще зададим нашему вновь испеченному плавающему блоку еще и отступ margin в 5px со всех сторон (margin:5px), чтобы было понятнее его взаимоотношение с соседними тэгами:

Наш элемент начинает плавать влево (ибо мы прописали float:left). При этом заработали ширина и высота, заданные в правилах height и width, не смотря на то, что Span изначально был строчным тегом. Кроме этого заработал и margin по высоте (отступ до соседей), который для строчных тэгов изначально был бесполезен.

Отсюда мы делаем вывод, что после прописывания float элемент стал совершенно другим и не похожим на то, чем он был до этого. Кроме этого он стал по другому взаимодействовать с другими тегами.

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

Чаще всего это будет контейнер Div — идеален для построения блочной схемы, т.к. изначально имеет нулевые margin и padding, а height и width у него имеют значение Auto. Т.о. Div является структурным блоком, так же как и Span, у которого тоже все нулевое.

Но давайте вернемся к нашим баранам, а именно опишем все те изменения, которые происходят с тегом, когда к нему применяется правило Float со значением Left или Right:

  1. В не зависимости от того, каким он был до этого, он становится блочным (соответствует display:block)
  2. Не смотря на то, что он становится блочным, его размер будет определяться объемом заключенного в него контента (проявляется некоторая специфика). Т.е. если я в нашем примере уберу значение ширины плавающего контейнера (width:250px), то ширина его будет уже определяться количеством заключенного в него текста:
  3. Плавающий элемент (с float left или right) в «Margin-colloapse» не участвует, т.е. не делится с соседними элементами своими отступами.
  4. Они не замечают соседние блочные элементы (с display: block), т.е. они с ними не взаимодействуют. Это можно видеть из приведенного чуть выше скриншота, где зеленый блок (div — зеленый прямоугольник) стоит так, как будто бы плавающего Span и не существует.
  5. А вот строчные тэги (с display: inline) обтекают плавающие блоки. На приведенном чуть выше скриншоте это видно по тому, что текст заключенный в Div обтекает Span.

Clear (both, left, right) и горизонтальное меню на Float


Возникает вопрос: а можно ли блоки, стоящие в коде ниже плавающего элемента (с float:left или right), заставить с ним взаимодействовать (т.е. выстраивать свое положение в зависимости от размеров плавающих блоков)? Оказывается можно, и для этого в CSS предусмотрено специальное правило Clear. Оно имеет четыре допустимых значения (none используется по умолчанию):

Когда мы для какого-либо Html тега прописываем CSS правило Clear, то это означает, что этот самый элемент должен будет учесть все плавающие и стоящие перед ним в коде блоки:

  1. Слева, если прописан clear:left
  2. Справа при right
  3. Везде при clear:both (означает с обеих сторон)

Давайте попробуем посмотреть на примере clear:left для приведенного чуть выше скриншота (его мы пропишем для зеленого Div контейнера):

<span style="background:#FFC0C0;height:30px; width:250px;float:left;margin:5px;">Float блок</span>
<div style="background:#C0FFC0;clear:left;">Блочный</div>
<div style="background:#C0C0FF;">Блочный</div>

Т.о. мы заставили контейнер Div увидеть и учесть плавающий слева от него элемент. Если для этого же тега прописать clear:right, то никаких изменений не произойдет, ибо плавающих вправо блоков (с right) у нас в коде перед этим тэгом не наблюдается.

Если же использовать clear:both, то будут учтены все плавающие блоки (и влево, и вправо — какие найдутся). Both используют в тех случаях, когда неизвестно с какой из сторон появится элемент плавающий и высокий. Именно его и можно чаще всего встретить в коде в наше время.

Ну, и давайте на небольшом примере посмотрим для чего же может быть использовано Float при верстке сайта. Дело в том, что с помощью плавающих блоков можно создать горизонтальное меню из обычного списка. Пусть у нас изначально имеется маркированный Html список UL такого вида:

<ul class="menu">
	<li><a href="#">Пункт 1</a></li>
	<li><a href="#">Пункт 2</a></li>
	<li><a href="#">Пункт 3</a></li>
	<li><a href="#">Пункт 4</a></li>
	<li><a href="#">Пункт 5</a></li>
<ul>

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

Теперь давайте уберем маркеры с помощью CSS правила list-style со значением None, а также сделаем строчные теги гиперссылок блочными с помощью display:block, подсветим их каким-либо фоном и зададим небольшие внешние отступы margin для элементов списка, чтобы их расклеить друг от друга.

Для разнообразия попробуем задать свойства с помощью тега Style, который прописывается между открывающим и закрывающим Head:

<head>
<style type="text/css">
.menu{
	list-style:none;
	margin:0;
	padding:10px;
}

.menu li a{
	display:block;
	padding:10px;
	background:#ccf;
}
.menu li{
	margin:5px;
}
</style>
</head>

В результате картинка нашего будущего шедевра будет выглядеть гораздо более похожим на меню, но, правда, на меню вертикальное, а нам ведь хочется создать горизонтальное с помощью Float:

Сделать из этого меню горизонтальное можно будет, всего лишь добавив элементу списка Li правило float:left:

.menu li{
	margin:5px;
        float:left;
}

Почему получилось именно так? Плавающий блок (с float отличным от none), когда ему надо выстроиться, смотрит на соседние тэги, на границы контейнера, и встает так высоко на вебстранице, как только сможет. Так и сделал «Пункт 1» — встал максимально высоко как только мог и потом уже поехал влево (ибо у него прописано float:left).

«Пункту 2» тоже хватило места встать максимально высоко, а затем он поехал влево и уткнулся в предыдущий плавающий блок. Тоже самое можно сказать и об остальных пунктах нашего горизонтального меню. Но что же произойдет, если в контейнере по ширине не будет хватать места для всех пунктов меню? Давайте посмотрим, искусственно сузив область просмотра:

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

Но если бы, например, высота первого пункта оказалась бы больше, чем у четвертого, по которому «Пункт 5» определил свою верхнюю границу, то получится такая вот картина:

Если слишком высоким окажется «Пункт 4», то картина изменится на такую:

В этом случае «Пункт 5» выровнялся по высоте последнего плавающего блока и не встретив никого препятствия на пути доехал до левой границы контейнера.

Отсюда, кстати, следует вывод, что если текст в пунктах такого горизонтального меню на основе css правила float будет очень длинным, то может получиться именно так, как было показано на предыдущих скриншотах. Возможно, что делать подобное меню будет проще с помощью фоновых картинок, размер которых фиксирован. Можно использовать и display:table, но создание таких меню это уже тема отдельной статьи и, возможно, даже не одной.

Блочная верстка — создание колонок в макете с помощью Float


Но основное предназначение Float это, конечно же, создание колонок при использовании блочной верстки. Я уже об этом очень подробно писал в серии статей, посвященной созданию двух и трехколоночных макетов при Div верстке.

При создании макета страниц вам всегда будет необходимо выстраивать блочные области друг рядом с другом (например, область левой колонки, область с контентом и правой колонки). Обычные блоки в CSS встают друг под другом. Как же их поставить друг рядом с другом? Конечно же, с помощью плавающих элементов на основе Float.

Более подробно создание двух и трехколоночного макета вы сможете изучить по приведенной чуть выше ссылке, а здесь я озвучу только заложенную в этом идею без ее дальнейшей детализации. Изначально берутся три контейнера Div с присвоенными ими классами.Они и будут образовывать в конечном счете наши колонки:

<body>
	<div id="left">Содержимое левой колонки</div>
	<div id="right">Содержимое правой колонки</div>
	<div id="center">Текст области контента</div>
</body> 

Затем для классов контейнеров левой и правой колонки задаем float:left и right (контейнеры для наглядности подсвечиваются фоном с помощью background), а также ограничиваем их ширину с помощью width:

<head>
<style type="text/css">
#left{
	background:#ccf;
        width:100px;
        float:left;
}
#right{
	background:#fcc;
        width:150px;
        float:right;
}
#center{
	background:#cfc;
}
</style>
</head>

Таким образом мы получили две боковые колонки фиксированной ширины с помощью волшебного правила Float. Остается только разобраться с областью контента:

Далее нужно центральную колонку отодвинуть слева на ширину левой, а справа — на ширину правой с помощью все того же правила margin (а именно для нашего примера margin:0 150px 0 100px;):

#center{
	background:#cfc;
        margin:0 150px 0 100px;
}

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

Удачи вам! До скорых встреч на страницах блога KtoNaNovenkogo.ru

Подборки по теме:

Комментарии и отзывы

Александр

Спаасибо, многому научился благодаря вашему блогу. Подскажите пожалуйста. Такая ситуация: главная страница, анонс новости, а под ним аватар (типа «booble») коммента и кол-во комментов в цифрах. Мне нужно, чтобы эта связка booble+цифра отображалась в той же строке где и окончание новости. А она всё равно отображается под анонсом новости. Вот код:

<a href="#commentspost">

— анонс новости, а интересующие комменты

Дмитрий

Александр: ну, точно сказать не могу, но я бы попробовал CSS свойство display: inline

Артур

Здравствуйте!Скажите пожалуйста, имеет ли значение последовательность элементов имеющих значение float в html коде? Я создал три элемента div в следующей последовательности — div id="left" div id="center" div id="right", и div id="right" прилепился к правому краю, но не встал на уровне с другими элементами, а спустился вниз, под div id="center"! Как только я поменял их местами и восстановил такой порядок как показано у вас, то все стало на место! Вот почему такой вопрос! Спасибо

Сергей

Спасибо, у Вас хороший блог!

«В этом случае «Пункт 5» выровнялся по высоте последнего плавающего блока и не встретив никого на пути доехал до левой границы контейнера.»

Скажите а как можно реализовать также, как на третьем с конца изображении, но, чтобы блоки упирались плотно в верхние?

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

Никита

3.Плавающий элемент (с float left или right) в «Margin-colloapse» не участвует, т.е. не делится с соседними элементами своими отступами.

буква o лишняя

Павел

самый лучший урок в интернете! Спасибо автору статьи!

Илья

Спасибо, хороший урок, но я бы порекомендовал комплексное обучение по урокам Дмитрия Охрименко ( CSS+HTML ) — http://itvdn.com/ru/video/html5-and-css3

Денис

Здравствуйте!

Подскажите пожалуйста, почему при элементы с float:(left,right) не имеют высоты, если их «засунуть» в блочный элемент??!!

ПОМОГИТЕ!!!

----------#menu{

width: auto ;

margin:50px 50px;

background: #ccc;

border: 2px dotted;

}

#menutop{

display: block;

vertical-align: middle;

margin: 30px ;

border:2px dotted yellow;

}

#menutopelements{

display:inline-block;

border:2px dotted ;

margin:10px;

}

#menubottom{

display:block;

vertical-align:middle;

border:2px dotted turquoise;

height:50px;

}

ul{

margin:0;

}

#elements {

background: #f1034c;

display:inline;

float:left;

width:33%;

height: auto;

}

----------------

Title

lorem ipsum

xfgh

arb

szasdf

ZSd

Подписаться не комментируя