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

На этой странице:

Сначала рассмотрим абсолютное позиционирование блочных элементов, а затем уточним приведённые алгоритмы для строчных элементов.

Вверх Позиционирование блочных элементов

Абсолютно позиционированный блок изымается из потока

Абсолютно позиционированный блок изымается из потока и может располагаться в любом месте над потоком (перекрывая его).

По умолчанию браузер выполняет вёрстку потоком: блоки выводятся прямоугольниками сверху вниз, занимая всю доступную ширину родителя (значение свойства width) вместе с границами и всеми своими отступами.

Если для какого-то блока указать абсолютное позиционирование (position:absolute), он изымается из потока, а на его место подтягиваются блоки, которые шли за ним в потоке.

Идентификаторы или классы?

CSS-определение можно связать с элементом при помощи класса (class=имя) или идентификатора (id=имя). Нужно помнить только одно важное правило:

Элементов с одним и тем же классом может быть на странице много, а каждый идентификатор — уникален.

Поставим несколько опытов. Зададим на странице три блока:

<BODY>
  <DIV id=block1>Блок 1</DIV>
  <DIV id=block2>Блок 2</DIV>
  <DIV id=block3>Блок 3</DIV>
</BODY>
          

Чтобы прямоугольники, ограничивающие блоки, были лучше видны, зададим границы, внутренние отступы и фон:

Посмотреть

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

BODY { margin:0; padding:0; }
#block1, #block2, #block3
{
  border: 1px solid black;
  background:cyan;
  padding: 10px;
  text-align:right;
}
          

Посмотреть

Что произошло:

  • блок изъят их потока (расположенный ниже блок подтянулся на его место);
  • занимает положение “выше” потока (по отношению к читателю);
  • координаты верхнего левого угла не изменились;
  • размеры установились по содержимому.

Зададим для второго блока абсолютное позиционирование и покрасим его в другой цвет:

#block2
{
  position:absolute;
  background:#fff2a6;
}
          

Видим, что блок изымается из потока, сохраняя прежние координаты верхнего левого угла (для языков с написанием справа налево сохранились бы координаты правого верхнего угла). Кроме того, замечаем, что горизонтальный размер блока перестаёт подстраиваться под ширину родителя, а устанавливается по содержимому.

Абсолютно позиционированный блок можно поместить в любое место, задавая смещения при помощи свойств: left, top, right, bottom.

Для абсолютно позиционированного блока эти свойства описывают смещения относительно ближайшей стороны блока-контейнера.

Блоком-контейнером считается ближайший предок, значение position которого отлично от stаtic, а если таких предков нет, то элемент HTML.

top, right, bottom, left
Значения: <размер> | <проценты> | auto | inherit
По умолчанию: auto
Область применения: позиционированные элементы (т. е. элементы, для которых position не равно static)
Наследование: нет
Проценты: относительно высоты блока-контейнера для top и bottom и ширины блока-контейнера для right и left

Иллюстрация демонстрирует положения блока при разных наборах свойств left, top, right и bottom.

Поместить блок в левый верхний угол можно при помощи определения:

#block2
{
  position:absolute;
  left:0;
  top:0;
  background:#fff2a6;
}
          

Посмотреть

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

Для языков с написанием справа налево утверждение справедливо для правого верхнего угла.

Если задать только одно смещение (например, left), второе (top) сохранит то значение, которое имелось бы у блока в потоке.

#block2
{
  position:absolute;
  left:100px;
  background:#fff2a6;
}
          

Посмотреть

Так как задано нулевое расстояние блока от левого и правого края, он вынужден растягиваться, занимая всю ширину (вместе с границей и всеми своими отступами).

К сожалению, указание противоположных смещений не работает в браузере IE (для языков с написанием слева направо он выполняет left:0, но игнорирует right:0).

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

#block2
{
  position:absolute;
  top:120px;
  left:0;
  right:0;
  background:#fff2a6;
}
          

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

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

Простой ответ “относительно родительского блока” оказывается верным, если для родителя также задано позиционирование (любое, кроме static). Если это не так, смещения откладываются от “дедушки”, то есть от родителя родителя. Если дедушка не позиционирован, то от его родителя. И так далее до корня иерархии, то есть до HTML.

Первый предок, у которого значение position отлично от stаtic (или HTML, если таких блоков нет) считается блоком-контейнером данного блока.

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

Посмотреть

Так как BODY не позиционирован, смещения отсчитываются от HTML, то есть от границ документа. Именно документа, а не области просмотра.

Область просмотра (viewport) перемещается по документу при скролировании, и верхний левый угол документа уходит за её пределы.

В рассмотренном примере смещения отсчитывались именно от HTML, так как элемент BODY не был позиционирован:

BODY { margin:0; padding:0; }
#block1, #block2, #block3
{
 border: 1px solid black;
 background:cyan;
 padding: 10px;
 text-align:right;
}
#block2
{
  position:absolute;
  left:100px;
  top:100px;
  background:#fff2a6;
}
          

Посмотреть

Видим, что положение позиционированного блока на экране не изменилось.

Чтобы убедится, что начало отсчёта связано именно с HTML, зададим для BODY внешний отступ:

BODY 
{ 
  margin:50px; 
  padding:0; 
}
          

Посмотреть

Смещения блока стали отсчитываться от границ BODY. Само BODY осталось на месте, так как для него смещения не заданы.

А теперь назначим для BODY относительное позиционирование (не задавая никаких смещений):

BODY 
{ 
  position: relative;
  margin:50px; 
  padding:0; 
}
          

Посмотреть

Зададим для BODY толстую синюю рамку (border: 10px solid blue), внутренний отступ (padding:10px;), а для блока укажем нулевые left и top.

Блок “прилип” к левому верхнему углу внутреннего отступа BODY.

Это означает, что начало координат для left и top совпадает именно с этой точкой.

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

Стало понятным, откуда отсчитываются смещения — от внешней границы внутреннего отступа первого позиционированного предка.

Разберёмся теперь с тем, до каких именно границ смещаемого блока они распространяются.

Внутренний отступ у нас уже задан для всех блоков. Увеличим ширину границы и зададим внешний отступ для второго блока:

Посмотреть

Внешний край внешнего отступа смещаемого блока условно обозначен пунктирной линией. Именно он “прилип” к началу координат.

#block2
{
  position:absolute;
  background:#fff2a6;
  left:0; top:0;
  margin:20px;
  border: 10px solid red;  
}
          

Видим, что смещение распространяется до внешнего края внешнего отступа смещаемого блока.

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

Смещения left, top, right и bottom для абсолютно позиционированного блока отсчитываются от сторон прямоугольника, проведённого по внешней границе внутреннего отступа первого позиционированного предка (или HTML, если другие позиционированные предки отсутствуют).

Смещения распространяются до внешних краёв внешних отступов смещаемого блока. То есть у блока смещается всё: внешние отступы, рамка, внутренние отступы и содержимое.

Вверх Позиционирование строчных элементов

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

Пусть HTML-код записан в следующем виде:

  <BODY>
    <H1>Абсолютное позиционирование</H1>
    <P>
В этом абзаце есть <STRONG>выделенный фрагмент текста</STRONG>. Для 
этого фрагмента задано абсолютное позиционирование.
    </P>
  </BODY>
          

Посмотреть

Позиционирование не задано ни для одного элемента, поэтому свойства left и top, заданные для STRONG игнорируются.

Игнорируется и свойство width, ведь элемент STRONG — строчный, а для строчных элементов свойства width и height не работают.

Зададим стилевые правила:

BODY { margin:10px; padding:0px; }
    
P { border: 1px solid black; }    
    
STRONG
{
  left:100px; top:150px;           
  width:10em;
  padding:10px;
  background:cyan;
  border: 1px solid black;
}
          

Посмотреть

Элемент STRONG превратился в блочный и сместился на заданные расстояния по отношению к HTML, так как ни родитель P, ни дедушка BODY не позиционированы.

Зададим для STRONG абсолютное позиционирование:

STRONG
{
  position: absolute;           
  left:100px; top:150px;           
  width:10em;
  padding:10px;
  background:cyan;
  border: 1px solid black;
}
          

Посмотреть

Теперь смещения элемента STRONG отсчитываются от позиционированного родителя P.

Добавим к свойствам P относительное позиционирование (без каких либо смещений):

P 
{ 
  position: relative;           
  border: 1px solid black; 
}    
          

Вверх Значение auto

При абсолютном позиционировании значения auto для всех смещений, кроме bottom означают такие величины, какие были бы у элемента, если бы он находился в потоке. Тот же эффект возникает, когда смещение не задаётся вовсе.

Рассмотрим этот вопрос подробнее. Пусть HTML-код записан в следующем виде:

  <BODY>
    <H1>Значение auto</H1>
    <P>
В этом абзаце есть выделенное <STRONG>слово</STRONG><SPAN>*</SPAN>. 
За этим словом следит маркер в виде красной звёздочки.
    </P>
  </BODY>
          

Посмотреть

Вот так выглядит изображение, когда не заданы стили.

Зададим следующий набор определений:

Посмотреть

Абсолютно позиционированная звёздочка прилипла к левой границе BODY — первого своего позиционированного предка. Так произошло потому, что задано left:0.

Смещение по вертикали осталось таким, каким было в потоке. Так произошло потому, что задано: top:auto.

BODY 
{
  position: relative; 
  margin: 10px 10px 10px 2em;
  border-left: 1px dotted black;
  padding-left: 10px;
}
SPAN
{
  position: absolute; 
  left:0;
  top:auto;
  color:red;
  font-weight:bold;
}
          

Посмотреть

Для смещений разрешается задавать отрицательные значения.

Сместим звёздочку в левый внешний отступ BODY, задав отрицательное смещение для left:

SPAN
{
  position: absolute; 
  left:-1em;
  top:auto;
  color:red;
  font-weight:bold;
}
          

Посмотреть

Маркер, действительно, следит за выделенным словом.

Уменьшим ширину окна так, чтобы выделенное слово переместилось в следующую строку. Звёздочка так же сместилась на строку ниже. Смещение top получает то значение, которое элемент имел бы в потоке.

Если для свойств left, width и right задать значение auto, то левый край помещается в его статическое положение (правый край для языков с написанием справа налево), ширина определяется по содержимому, а противоположное смещение вычисляется так, чтобы достичь границы блока, по отношению к которому элемент позиционируется.

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