При всех своих особенностях, блочная модель HTML имеет одно неоспоримое преимущество: она отлично подходит для вывода текста. В процессе создания HTML мало кто задумывался, что настанет день, когда язык будет использован для таких сложных макетов, которые сейчас встречаются почти на каждом сайте. Предполагалось, что текст, ссылки и картинки - основа на века. :)
На сегодняшний день львиная доля работы верстальщика занимает именно верстка блоков. С текстами как-то попроще получается, а вот блоки нужно расставить и оформить согласно дизайна. Сделать это только отступами и размерами будет затруднительно. Нужно научиться позиционировать блоки.
Позиционирование по своей сути означает расположение блока в какой-то указанной позиции. В HTML с этим всё не так просто, поскольку в нём используется несколько видов указания положений элемента. В CSS переключателем такого режима является свойство position. Оно может принимать несколько значений.
Самый простой вариант - static. Этот вариант мы, собственно, уже расмотрели, поскольку для всех тэгов оно используется по-умолчанию. Данное позиционирование означает вывод блока в обычном потоке. Мы можем как бы «сдвинуть» элемент используя margin и padding, но это будет только иммитация, поскольку начало координат блока относительно страницы (или родительского блока) изменить нельзя.
Значение fixed позволяет расположить блок в произвольной точке относительно края браузера. В этом варианте положение блока не меняется при прокрутке страницы. Положение же блока указывается значениями: left, right, top и bottom. У них обычные единицы измерения, например px.
<div style="background: gold; width: 150px; height: 150px; position: fixed; top: 0; left: 0;"> текст </div>
Fixed чаще всего используется там, где нужно вывести блок, не меняющий своего положения при прокрутке страницы.
Следующий вариант - relative. Здесь блок будет позиционироваться относительно своего исходного положения. Сдвиг блока осуществляется так же с помощью left, right, top и bottom.
<div style="background: gold; width: 150px; height: 150px; position: relative; top: 30px; left: 100px;"> текст </div>
Relative используется прежде всего там, где нужно точно спозиционировать блок относительно родителя. Например в наших примерах в схлопывающихся отступах, для блоков можно было бы попробовать указать «position: relative» и указать top-отступ безо всяких margin'ов.
Самое сложное свойство - absolute. При его использовании нужно учитывать значение position родительского блока. Если у родителя это static (что равно не указанному position вовсе), то началом координат будет окно браузера. Но если у родителя указать relative, absolute или fixed, то точкой начала координат будет уже родительский элемент.
<div> <div style="background: yellow; width: 200px; height: 30px; position: absolute; top: 10px; left: 100px"> текст </div> </div>
Теперь укажем у родителя relative.
<div style="position: relative;"> <div style="background: yellow; width: 200px; height: 30px; position: absolute; top: 10px; left: 100px"> текст </div> </div>
Очевидно, что значением absolute не стоит злоупотреблять при верстке, поскольку не всегда очевиден конечный результат.
Поток вывода документа
Понятие потока очень простое: блоки и любые элементы HTML-страницы выводятся ровно в том порядке, как они и указаны в коде. Браузер видит блочный тэг - делает новую строку и выводит блок. Видит строчный - без переноса выводит этот элемент. И так элемент за элементом.
Смысл такого поведения лежал в низких скоростях соединения с Интернетом.
При таком выводе все элементы позиционируются автоматом относительно предыдущего. При выводе текста - проблем не возникает. Но только не при выводе блоков. Если нам нужно вывести блок в произвольном месте, то мы должны как-то указать это браузеру. Свойство position, как раз одно из тех свойств, которые влияют на поток вывода документа.
Принципиальное различие между значениями position в том, что одни устанавливают точку отсчета блока относительно браузера, а другие относительно стандартного потока вывода. Верстальщик должен понимать эти вещи, потому что достаточно проблематично верстать шаблон на позиционировании от края браузера. Гораздо проще использовать стандартный поток вывода и позиционировать все элементы от общих к частному. Например вначале задать общий контейнер, который будет спозиционирован от тэга HTML (окно браузера); вложенный блок шапки - уже будет задан от точки контейнера; какой-то блок в шапке - уже относительно основного блока шапки и т.п.
При таком способе вёрстки происходит сочетание полезных свойств static и relative. Там, где нет смещения блоков - position равен static, то есть его можно не указывать. Там, же где нужно задать сдвиг, делаем relative и указываем нужное значение.
Модульная сетка
Возьмем для примера мой сайт. Мы видим пять основных макетных блоков:
- Основной контейнер. Имеет фиксированную ширину и спозиционирован по центру браузера.
- Шапка сайта. Ширина 100% контейнера.
- Блок вывода контента (текста). Выравнивание влево в контейнере. Фиксированная ширина.
- Сайдбар. Выровнен вправо. Фиксированная ширина.
- Подвал. Вся ширина контейнера.
Для наглядности я оформил эту схему в цветах.
Данная схема есть ни что иное, как модульная сетка сайта. Запомните: всегда(!) перед созданием шаблона продумывайте модульную сетку. Поначалу рисуйте её на бумаге или в какой-нибудь программе. После придет опыт и модульную сетку вы сможете легко строить в голове.
Строится она очень просто: вначале выделяем из дизайна основной контент. После блок шапки, основного содержимого, подвала. Дальше дробим каждый блок на другие функциональные блоки. Верстаем же шаблон точно в таком же порядке!
Обратите внимание на соседние блоки: КОНТЕНТ и САЙДБАР. Это довольно сложное расположение, которое одним position добиться очень сложно. Вместо этого используется механизм плавающих блоков.
Плавающие (float) блоки
Строго говоря float-блоки это попытка верстальщиков использовать css-свойство там, для чего оно не предназначено. На сегодняшний момент работа с float-блоками достигла таких высот, что в ближайшей перспективе никаких других альтернатив не предвидится.
Вообще свойство float предназначалось для задания обтекания текстом картинок. Вот примерно так:
Ex ridens accusamus democritum duo, ne ponderum mandamus est. In usu nibh voluptaria deterruisset, ad pri adhuc graecis, quidam ullamcorper nam ei. Alterum vocibus blandit ex his, vix et soluta persequeris. Te discere phaedrum his, nisl semper has in, ius docendi euripidis an. Nam ex movet partiendo, mel et postea aliquam tractatos. Ei his saepe dissentiunt. Ea est deleniti abhorreant, ne dolore aliquip mei. Assum apeirian necessitatibus in quo, mea similique intellegam ex. Mei expetenda posidonium ne.
У float есть несколько значений, которые задают выравнивание элемента.
- left - элемент слева
- right - элемент справа
То есть блок выравнивается по краю родительского элемента.
Это свойство так и осталось бы применимым только к изображениям, если бы вебмастера не придумали его использовать для задания модульной сетки. Современная вёрстка во многом и заключается в том, чтобы правильно научиться управлять плавающими блоками.
Вывод float-блока в потоке
Рассмотрим простой пример. Сделаем родителя. Для наглядности зададим ему фон. И пусть будет произвольный текст и плавающий блок. Расположим текст перед блоком.
<div style="background: yellow;"> Ex ridens accusamus democritum duo, ne ponderum mandamus est. In usu nibh voluptaria deterruisset, ad pri adhuc graecis, quidam ullamcorper nam ei. Alterum vocibus blandit ex his, vix et soluta persequeris. Te discere phaedrum his. <div style="float: left; background: gold; width: 100px; height: 100px;">блок</div> </div>
Довольно странное поведение плавающего блока, не так ли? Обтекание произошло почему-то только по последней строке.
Теперь тоже самое, только текст после.
Теперь текст и плавающий блок ведут себя предсказуемо. В чем разница? Всё дело в том, что браузер в первом варианте вначале вывел текст, и только после этого выводит блок. Причем точка координат получается по последней строчке текста. Поэтому мы и видим обтекание только последней строчки.
Во втором же случае, браузер вначале позиционирует блок, а уже после выводит текст. Точка начала координат уже не зависит от текста.
Несколько float-блоков рядом
Посмотрим как ведут себя два и более float-блока рядом.
Расположим рядом пять float-блоков разной высоты. Для родителя я задал ширину, чтобы немного уменьшить размер картинки.
<div style="background: yellow; width: 350px; "> <div style="float: left; background: gold; width: 100px; height: 100px;">1</div> <div style="float: left; background: red; width: 100px; height: 120px;">2</div> <div style="float: left; background: blue; width: 100px; height: 130px;">3</div> <div style="float: left; background: green; width: 100px; height: 140px;">4</div> <div style="float: left; background: gray; width: 100px; height: 150px;">5</div> Ex ridens accusamus democritum duo, ne ponderum mandamus est. </div>
Мы видим, что плавающие блоки рядом заполняют собой всю ширину контейнера. Тот блок, который уже не помещается, переносится на новую строку. Текст, как ему и положено обтекает все блоки. Обратим внимание на одну особенность: основной контейнер (желтый цвет) имеет высоту не всей «конструкции», а только по тексту. Последние два плавающих блока «висят» вне контейнера.
Это еще одна из особенностей float-блоков. Браузеры их как бы вычленяют из стандартного потока вывода и выводят вне контекста родительского элемента. То есть вроде бы блоки есть и они должны быть внутри родителя, но визуально их нет. :)
Оставим два блока в родителе и уберем текст.
<div style="background: yellow; width: 350px; "> <div style="float: left; background: gold; width: 100px; height: 100px;">1</div> <div style="float: left; background: red; width: 100px; height: 120px;">2</div> </div>
Родитель исчез. Для проверки добавим родительскому блоку border: 1px solid green.
Мы видим совершенно пустой родительский блок в зеленной рамке. Почему, а самое главное, как с этим бороться? Ведь нам нужно будет позиционировать блоки после блока родителя, а он получается нулевой высоты...
<div style="background: yellow; width: 350px; border: 1px solid green;"> <div style="float: left; background: gold; width: 100px; height: 100px;">1</div> <div style="float: left; background: red; width: 100px; height: 120px;">2</div> </div> <div style="background: blue; width: 350px; height: 150px;">3</div>
Третий блок по-идее должен быть под вторым, но на самом деле он оказывается сразу после родителя первых блоков.
Понятно, что такое отображение объясняется поведением float-блоков, поэтому существует css-свойство, которое имеет своей целью прекратить обтекание в блоках. Это что-то вроде «Стоп! Больше нам обтекание не нужно!».
Свойство clear имеет несколько значений. Наиболее употребительны:
- both - прекратить обтекание со всех сторон
- left - прекратить обтекание слева
- right - прекратить обтекание справа
Если перед clear-элементом есть float-элемент, то clear-элемент отменит обтекание. Добавим в последнем примере для третьего блока clear.
<div style="background: yellow; width: 350px; border: 1px solid green;"> <div style="float: left; background: gold; width: 100px; height: 100px;">1</div> <div style="float: left; background: red; width: 100px; height: 120px;">2</div> </div> <div style="background: blue; width: 350px; height: 150px; clear: both;">3</div>
Это уже более предсказуемое поведение, но остался вопрос: как же «вернуть» высоту родительского элемента?
Для таких случаев в верстке применяется дополнительный «отсекающий» блок в самом конце родителя.
<div style="background: yellow; width: 350px; border: 1px solid green;"> <div style="float: left; background: gold; width: 100px; height: 100px;">1</div> <div style="float: left; background: red; width: 100px; height: 120px;">2</div> <div style="clear: both;"></div> </div> <div style="background: blue; width: 350px; height: 150px;">3</div>
Вот теперь, похоже, это ровно то, что нам нужно.
Итоги урока
Позиционирование и плавающие блоки изначально создавались вовсе не для того, чтобы их использовали для сложной вёрстки сайтов. Но так уж сложилось исторически, что именно на этом базируется вся современная верстка сайтов. И именно поэтому верстальщику нужно понимать основы такого «странного» поведения блочной модели и float-блоков и с умом это использовать в своей работе.
Комментариев: 8 RSS
1dark10427-01-2012 07:38
Уже интереснее, ждём продолжения.
2Андрей Морковин27-01-2012 09:26
Очень хорошо написано. С интересом прочитал.
Максим, я тут недавно обнаружил очень приятный сервис: http://jsfiddle.net, благодаря которому можно в одном окошке выводит HTML+CSS+Результат (как вот здесь http://homm.strategia.su/2011/11/16/1/). Возможно Вы знаете о его существовании, но для меня это было сюрпризом.
Думаю, для публикаций данного цикла статей удобно им воспользоваться: не нужно снимать скриншоты.
3Аноним27-01-2012 09:36
Да, интересный сервис. Раньше видел, но как-то и в голову не пришло, что его можно использовать для отладки и обучения. :)
4Аноним27-01-2012 09:53
Небольшое дополнение - при позиционировании блока с указанным position:absolute; учитывается любое значение родительского контейнера за исключением position:static; (т. е. в том числе и position:fixed;)
5Аноним27-01-2012 10:10
Ок.
6Аноним28-01-2012 08:44
Уроки тянут на целую книгу.
Ее можно сделать в pdf или даже издать в печатном виде ;-)
7Максим04-04-2012 18:04
Как сделать чтобы текст родительского блока обтекал вложенные?(тоесть когда они закончатся занимал всю ширину блока а не тока край)
8Богдан25-05-2012 15:37
Огромное спасибо за столь детальное обьяснение. Очень долго не мог толком понять процесс позиционированния - а тут все так ясно)