Работа с CSS: основы (часть 2)



Итак, продолжаем знакомство с CSS - технологией стилевого оформления документов. В этой статье мы сделаем, наверно, самую популярную раскладку - двухколоночную с верхней (header) и нижней (footer) частью. Создадим html-документ и подключим к нему внешний файл стилей:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   <title>megasite.com</title>
   <link rel="stylesheet" href="skin.css" type="text/css" />
   <meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
</head>
<body>
   <div id="header">
      header
   </div>
   <div id="left">
      left
   </div>
   <div id="center">
      center
   </div>
   <div id="footer">
      footer
   </div>
</body>
</html>

Поясним: первый тег - doctype(тип документа), обязательное условие любого well-formed(соответствующего правилам) документа, написанного с помощью языка разметки xml-типа. Доктайпы могут разными, "они как бы говорят" браузеру в соответствии с какими стандартами отображать документ.

Дальше все должно быть понятно - тегом link подключается css-файл, идут 4 блока: header, left, center, footer. У каждого блока есть атрибут id="****", по которому блок однозначно идентифицируется в DOM-модели документа, но об этом (и об отличии атрибутов id и class) в одной из следующих статей. Сейчас(у нас ведь пока пустой файл css) эти блоки располагаются один за одним, каждый во всю ширину окна, что-то вроде этого:

Расположение блоков в html без css-стилей

Нам понадобится такая заготовка листа стилей:

body {
}
#header {
}
#left {
}
#center {
}
#footer {
}

Селектор body означает, что мы пишем стили для тега body, а селекторы типа #header - предшествует обьявлению для элемента с id равным header. В последнем случае также можно использовать селектор div#header.

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

body {
   padding: 0;
   margin: 0;
}
#header {
   height: 100px;
   background: red;
}
#left {
   height: 300px;
   background: blue;
   float: left;
   width: 200px;
}
#center {
   height: 350px;
   background: gray;
   margin-left: 200px;
}
#footer {
   height: 100px;
   background: yellow;
   clear: left;
}

У нас должно получиться:

Финальная раскладка блоков в html

Теперь обьясню:

padding: 0; и margin: 0; для тега body
Разные браузеры делают разые отступы у главного контейнера страницы - body, поэтому мы их обнуляем.
background: цвет
Этим обьявлением, как легко понять, мы назначаем разым блокам цвета, чтобы увидеть как они располагаются на страничке.
height: высота
Назначаем высоту нашим блокам. Чтобы они что-то из себя представляли, а не схлопнулись в одну строчку :) Когда они будут наполнены информацией, высоту нужно будет убрать.
width: 200px
Левая колонка, aka меню, пусть будет шириной 200px.
float: left
Это обьявление заставляет левую колонку прижаться к левому краю окна и изымает ее из потока блоков. Это означает что идущие за данным блоки, перестают его замечать и поднимаются на его место (содержимое этих блоков будет обтекать флоатнутый блок).
margin-left: 200px
Делаем для центрального блока внешний отступ слева в ширину левой колонки, чтобы они не пересекались.
clear: left
И, наконец, последнее обьявление - заставляет footer сдвигаться вниз до тех пор, пока слева не окажется блоков с указанным float. В результате пересечение футера и левой колонки исключено.

Надеюсь здесь все ясно. Теперь сделаем еще одну вещь - заставим footer быть всегда внизу окна, вне зависимости от высоты центральной или левой колонок. Для этого давайте познакомимся с абсолютным позиционированием: заданием position: absolute у блока. Такие блоки не учавствуют в потоке, их положение указывается с помощью свойств left, right, top, bottom - эти значения показывают на сколько блок отстоит от соответствующих сторон содержащего блока. Содержащий блок - это блок с заданным position: relative (относительное позиционирование), и в котором содержится позиционируемый блок. Если среди родителей нашего блока нет блоков с position: relative, то его положение отсчитывается от окна.

Следуя традиции, сразу приведу код, которым нужно дополнить css записанный выше:

html {
   height: 100%;
}
body {
   min-height: 100%;
   position: relative;
}
*html body {
   height: 100%;
}
#footer {
   position: absolute;
   bottom: 0px;
   width: 100%;
}

Теперь разбираем:

position: relative для body:
Делаем body содержащим блоком для футера. Об этом говорилось выше.
min-height: 100% для body:
Минимальная высота контейнера body теперь будет 100 процентов от высоты окна. Но, стойте, браузер ведь не знает пока этой высоты, соответственно не может вычислить высоту body. Поэтому нам нужно контейнеру, в котором находится body - html (вся область окна браузера), указать высоту 100%. Этим обьясняется правило html { height: 100%; }. Все было бы хорошо если бы не Internet Explorer 6, который не понимает свойства min-height. Нам поможет тот факт, что в IE нельзя фиксировать высоту(ширину) блоков - это значит, что если даже указать точную высоту, например, 100px, для блока, в IE он все равно будет растягиваться при переполнении содержимым.

Следовательно нам достаточно указать для body height: 100%, но нужно это сделать так, чтобы остальные браузеры не восприняли это обьявление. Здесь нам придет на помощь известный хак "Star HTML", который состоит в использовании конструкции *html. Все браузеры, кроме ИЕ6, игнорируют обьявления следующие за таким селектором, а это именно то что нам надо. Итак: *html body { height: 100%; }.
position: absolute и bottom: 0px для футера:
Обьявляем тип позиционирования у блока footer и задаем отступ от нижнего края содержащего блока.
width: 100%:
Блоки с абсолютным позиционированием(в нашем случае footer) перестают растягиваться по всей ширине родителя, как блоки в обычном потоке, поэтому насильно укажем ширину 100 процентов.

Вот и все, можете попробовать, должно получится что-то вроде этого:

Финальная раскладка блоков в html, футер прижат к низу окна

Есть одно "но" - если вы сожмете окно, футер налезет на центральную или левую часть. Чтобы от этого избавится нужно заключить их еще в один блок -

<div id="container">
   <div id="left">
      left
   </div>
   <div id="center">
      center
   </div>
</div>

И написать для него css-правило:

#container {
   overflow: hidden;
   width: 100%;
   padding-bottom: 100px;
}

Поясню:

Помните, блок с указанным значением float, изымается из потока и повисает над ним. Из-за этого контейнер container перестает содержать левую колонку и схлопывается до высоты центральной части (в случае если высота left больше высоты center). Чтобы заставить его обтекать и флоатнутый блок, одно из решений - указать overflow: hidden. Это обьявление значит - скрыть все, что вылезло за пределы блока. Переполнения блока у нас возникать не должно, таким образом мы получаем только результат побочного действия этого обьявления - container будет растягиваться в соответствии с высотой блока left.

Однако опять на пути встает упрямый ослик (ИЕ6), в нем данный побочный эффект наблюдается только у блоков с внутренним свойством в ИЕ "hasLayout". А container, в нашем случае, таким свойством не обладает. Вызвать "hasLayout" можно явно указав, например, ширину - width: 100%.

И последний штрих - указать container внутренний отступ снизу величиной в высоту футера. В этой высоте будет находится футер, а блоки left и center - нет.

Вот и все, раскладка готова. Продолжение следует.

Комментарии

Спасибо, хорошая получилась статья, только забыли рассказать почему в IE 6 при выполнении самого первого варианта между left и center появляется небольшой зазор. И как его убрать?

А на коментарии здесь, наверно, отвечать не принято!

Извините за задержку, был в отьезде.

  1. К сожалению, это особненность ИЕ - коряво вычислять размеры. Если вам нужно обозначить границу между левой и центральной частями - воспользуйтесь faux columns, или просто обозначайте только левую или правую часть.
  2. Если вы говорите о тн 3-х пиксельном баге, то есть несколько способов его решить. Например посмотрите у лебедева

Спасибо за помощь, разобрался.

Автору огромное человеческое СПАСИБО!!! Великолепнейшая статья!

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

Огромное спасибо автору! Статья наглядно демонстрирует принципы разметки с помощью CSS. Для меня как для новичка это просто супер!

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
  • Разрешаю теги: <a> <em> <strong> <pre> <ul> <ol> <li>
  • Строки и параграфы переносятся автоматически.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.

Подробнее о форматировании

Image CAPTCHA
Регистр символов учитывается.