Позиционирование

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

Краткий обзор

Суть позиционирования очень проста: любой бокс можно расположить в любом месте страницы, задав ему точные координаты. Именно любой, а не только <div>, как многим кажется; вы легко можете позиционировать хоть <b>, если очень захочется :-)

Существуют четыре способа позиционирования боксов:

Static

 

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

Absolute

 

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

Fixed

Ведет себя так же, как absolute, но при этом он не скролится вместе с остальной страницей.

Relative

 

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

Абсолютное позиционирование

Итак, чтобы расположить бокс абсолютно, ему надо задать нужный тип позиционирования и координаты:

#somebox {
  position:absolute;
  left:100px; top:100px;
  bottom:100px; right:100px;
}

Координаты означают расстояние бокса от краев: top:0 означает, что бокс прижат к верхнему краю, right:10px - что отстоит на 10 пикселов от правого края и т.д. Любая из координат необязательна. В случае, если координаты не задают вертикального или горизонтального положения, то оно остается таким же, какое было бы без позиционирования. То есть в случае, когда у нас есть два произвольных бокса один за другим "box1" и "box2":

<div id="box1">
 ...
</div>
<div id="box2">
 ...
</div>

... и второй мы позиционируем так:

#box2 {
  position:absolute;
  left:150px;
}

... то по вертикали он останется прямо под первым боксов, а по горизонтали будет отстоять от левого края на 150 пикселов.

Стакан

Возможно некоторых особенно въедливых читателей уже какое-то время беспокоит вопрос, который я намеренно опустил в начале: относительно каких таких краев двигают бокс координатные свойства? Вопрос этот не совсем тривиален, потому что хотя интуитивно и кажется, что все позиционируется "от окна", это не всегда так.

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

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

Используя более принятые в CSS термины, этот стакан называется "содержащим блоком" (containing block).

Fixed

Бокс с position:fixed - это, в общем-то, разновидность того же абсолютного позиционирования. Единственная разница заключается в том, что при скролировании окна эти боксы остаются на месте. Этот эффект широко используется на страницах веб-приложений для всяческих прилипающих блоков меню и тулбаров, которые как раз и должны себя так вести.

С fixed-боксами связан один среднеинтересный момент. Для обычных абсолютных боксов браузер всегда сделает достаточно скроллбаров, чтобы их можно было просмотреть. А вот если фиксированный бокс не влезет в окно, то доскролиться до него будет уже нельзя.

Автоматические размеры

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

#somebox {
  position:absolute;
  top:0; left:0; right:0;
  margin:20px; padding:20px;
}

Этот бокс с заданными левой и правой координатами будет точно касаться боковых сторон своего стака... э-э-э... содержащего блока, какой бы ширины тот ни был, а margin'ы и padding'и будут откладываться внутрь бокса.

Это свойство неоценимо при создании раскладок веб-приложений, где неперекрывающиеся боксы должны занимать весь экран по определенной сетке:

 

Засада

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

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

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

 

Здесь видны две проблемы:

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

Относительное позиционирование

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

Чаще же всего position:relative используют вообще без задания смещений. В этом случае он ведет себя как обычный статический бокс, но поскольку он все таки не статический, то он создает внутри себя содержащий блок, тот самый, относительно которого будут позиционироваться боксы внутри него.

Вот пример, который показывает полезность этого свойства. Пусть у нас есть три блока: "заголовок", "содержимое" и "низ", а внутри "содержимого" лежит блок "об авторе":

<div id="header">
</div>
 
<div id="contents">
  <div id="author">
  </div>
...
</div>
 
<div id="footer">
</div>

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

А теперь нам хочется внутри содержимого блочок об авторе расположить так, чтобы он был точно в правом верхнем углу содержимого.

 

Напишем ему:

#author {
  position:absolute;
  top:0; right:0;
}

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

Вот это и есть случай, в котором работает position:relative. Если мы поставим его блоку содержимого, то он никуда не денется из потока, но в то же время станет содержащим блоком, и "об авторе" расположится в его правом верхнем углу.

Автоматические размеры

В WinIE не работает задание размеров боксов через одновременную установку координат противоположных сторон. Это, однако, довольно легко обходится использованием интересной способности IE рассчитывать значения свойства для CSS с помощью Javascript. Возьмем тот же пример с боксом во всю ширину и margin'ами и padding'ами по 20 пикселов:

 

Код для этого выглядит так:

#somebox {
  position:absolute;
  top:0; left:0; right:0;
  margin:20px; padding:20px;
  border:solid red 1px;
}

Здесь IE просто проигнорирует right:0 и бокс останется у левого края, обтягивая свое содержимое:

 

Чтобы такого не было, ему надо задать какую-то конкретную ширину. Но поскольку указать ее точной цифрой мы не можем, так как неизвестно, какая ширина будет у родительского бокса, то мы заставим IE высчитывать эту ширину:

#somebox {
  position:absolute;
  top:0; left:0; right:0;
  margin:20px; padding:20px;
  border:solid red 1px;
  width:expression(document.body.offsetWidth-82);
}

document.body.offsetWidth - это текущая ширина бокса страницы. А число 82 - это margin'ы+padding'и+border'ы с двух сторон бокса.

Если нужно взять ширину не "body", а какого-то произвольного бокса, то ему надо дать id (пусть будет "mainbox") и тогда его ширина будет браться так: mainbox.offsetWidth.

Fixed

В WinIE не работает position:fixed. Это очень неприятно, потому что не только пропадает эффект прилипания (что было бы еще ничего), но бокс еще и не позиционируется совсем. А это, понятное дело, обычно полностью рушит всю раскладку.

Существует способ сымитировать поведение фиксированного позиционирования (чтобы бокс не скролился) с помощью абсолютного. Возьмем такую структуру:

<div id="contents">
</div>
 
<div id="menu">
</div>

Мы хотим, чтобы блок меню висел фиксировано в каком-нибудь месте, а содержимое бы свободно скролилось в окне. Если поставиь для меню position:absolute, то оно будет скролиться вместе с окном, потому что оно лежит внутри скролящегося окна. Гениальный же хак заключается в том, чтобы заставить скролиться не окно, а только бокс содержимого:

html {
  width:100%; height:100%;
  overflow:hidden;
}
 
body {
  width:100%; height:100%;
  margin:0; padding:0;
  overflow:auto;
}
 
#menu {
  position:absolute;
  top:20px; left:20px;
}

В деталях это означает следующее. Поведение элемента "html" во многом отвечает за поведение окна (так уж сложилось). Мы говорим ему занять все окно целиком и отключаем скроллинг (overflow:hidden). Зато элементу "body" говорим по размеру занять, опять-таки, все окно, а скроллинг включаем (overflow:auto). И теперь абсолютно подвешенный бокс "menu" не двигается, потому что скролится не его содержащий блок "html", а совсем другой - "body".

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

Заключение

Позиционирование обладает своими плюсами и минусами.

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

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

z-index

Описание

Любые позиционированные элементы на веб-странице могут накладываться друг на друга в определенном порядке, имитируя тем самым третье измерение, перпендикулярное экрану. Каждый элемент может находиться как ниже, так и выше других объектов веб-страницы, их размещением по z-оси и управляет атрибут z-index.

Синтаксис

z-index: число | auto

Аргументы

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

Кроме числовых значений применяется auto - порядок элементов в этом случае строится автоматически, исходя из их положения в коде HTML и принадлежности к родителю, поскольку дочерние элементы имеют тот же номер, что их родительский элемент.

Пример

HTML 4.01CSS 2.1IE 5.5IE 6IE 7Op 9.5Sa 3.1Ff 2.0Ff 3.0

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

 <head>

  <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">

  <title>z-index</title>

  <style type="text/css">

   #layer1, #layer2, #layer3, #layer4 {

    position: relative; /* Относительное позиционирование */

   }

   #layer1, #layer3 {

    font-size: 50px; /* Размер шрифта в пикселах */

    color: #000080; /* Синий цвет текста */

   }

   #layer2, #layer4 {

    top: -55px; /* Сдвигаем текст вверх */

    left: 5px; /* Сдвигаем текст вправо */

    color: #ffa500; /* Оранжевый цвет текста */

    font-size:70px;  /* Размер шрифта в пикселах */

   }

   #layer1 { z-index: 2; }

   #layer2 { z-index: 1; }

   #layer3 { z-index: 3; }

   #layer4 { z-index: 4; }

  </style>

 </head>

 <body>

  <p>Слой 1 наверху</p>

  <div id="layer1">Слой 1</div>

  <div id="layer2">Слой 2</div>

  <p>Слой 4 наверху</p>

  <div id="layer3">Слой 3</div>

  <div id="layer4">Слой 4</div>

 </body>

</html>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

 <head>

  <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">

  <title>z-index</title>

  <style type="text/css">

   #layer1, #layer2, #layer3, #layer4 {    position: relative; /* Относительное позиционирование */   }

   #layer1, #layer3 {    font-size: 50px; /* Размер шрифта в пикселах */

                            color: #000080; /* Синий цвет текста */   }

   #layer2, #layer4 {    top: -55px; /* Сдвигаем текст вверх */

                            left: 5px; /* Сдвигаем текст вправо */

                              color: #ffa500; /* Оранжевый цвет текста */

                             font-size:70px;  /* Размер шрифта в пикселах */   }

   #layer1 { z-index: 2; }     #layer2 { z-index: 1; }    #layer3 { z-index: 3; }

   #layer4 { z-index: 4; }

  </style>  </head>  <body>

  <p>Слой 1 наверху</p>

  <div id="layer1">Слой 1</div>

  <div id="layer2">Слой 2</div>

  <p>Слой 4 наверху</p>

  <div id="layer3">Слой 3</div>

  <div id="layer4">Слой 4</div>

 </body> </html>

Результат данного примера показан ни рис. 1.

 

Рис. 1. Применение параметра z-index

Объектная модель

[window.]document.getElementById("elementID").style.zIndex

Если не указывать значения z-index у элементов, по умолчанию будет установлен следующий порядок:

1.    Спозиционированные элементы в том порядке, в котором они присутствуют в HTML коде страницы (чем ниже они в коде, тем выше в порядке).

2.    Инлайновые элементы

3.    Не спозиционированные «плавающие» элементы в том порядке, в котором они присутствуют в коде страницы.

4.    Все не спозиционированные, не «плавающие», блочные элементы в том порядке, в котором они присутствуют в коде страницы.

5.    Фон и граница корневого элемента.

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

По умолчанию свойство z-index принимает значение auto, также оно может принимать целое значение или наследовать его. Целое значение может быть как положительным так и отрицательным, а также быть равным 0. Чем больше положительное значение, тем выше элемент в порядке и соответственно чем больше отрицательное значение - тем элемент ниже. По умолчанию элементы находятся на 0-м слое. В соответствии с этим порядок наложения теперь выглядит следующим образом:

1.    Спозиционированные элементы со значением z-index больше чем 0, затем в порядке появления в HTML коде страницы.

2.    Спозиционированные элементы в том порядке, в котором они присутствуют в коде страницы.

3.    Инлайновые элементы

4.              Не спозиционированные «плавающие» элементы в том порядке, в котором они присутствуют в коде страницы.

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

6.              Спозиционированные элементы со значением z-index меньше чем 0, затем в порядке появления в HTML коде страницы.

7.              Фон и граница корневого элемента.

 

 

© gruppa-43im2009

Конструктор сайтов - uCoz