Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
344 lines (239 sloc) 15.7 KB

Свойство "position"

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

position: static

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

Его можно также явно указать через CSS-свойство:

position: static;

Такая запись встречается редко и используется для переопределения других значений position.

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

<div style="background: #fee; width: 500px">
    Без позиционирования ("position: static").

    <h2 style="background: #aef; margin: 0">Заголовок</h2>

    <div>А тут - всякий разный текст... <br/>
         ... В две строки!</div>
</div>

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

Элемент с `position: static` еще называют *не позиционированым*.

position: relative

Относительное позиционирование сдвигает элемент относительно его обычного положения.

Для того, чтобы применить относительное позиционирование, необходимо указать элементу CSS-свойство position: relative и координаты left/right/top/bottom.

Этот стиль сдвинет элемент на 10 пикселей относительно обычной позиции по вертикали:

position: relative;
top: 10px;
*!*
<style>
  h2 {
    position: relative;
    top: 10px;
  }
</style>
*/!*

<div style="background: #fee; width: 500px">
    Заголовок сдвинут на 10px вниз.

    <h2 style="background: #aef; margin: 0;">Заголовок</h2>

    <div>А тут - всякий разный текст... <br/>
         ... В две строки!</div>
</div>

Координаты

Для сдвига можно использовать координаты:

  • top - сдвиг от "обычной" верхней границы
  • bottom - сдвиг от нижней границы
  • left - сдвиг слева
  • right - сдвиг справа

Не будут работать одновременно указанные top и bottom, left и right. Нужно использовать только одну границу из каждой пары.

Возможны отрицательные координаты и координаты, использующие другие единицы измерения. Например, left: 10% сдвинет элемент на 10% его ширины вправо, а left: -10% -- влево. При этом часть элемента может оказаться за границей окна:

*!*
<style>
  h2 {
    position: relative;
    left: -10%;
  }
</style>
*/!*

<div style="background: #fee; width: 500px">
    Заголовок сдвинут на 10% влево.

    <h2 style="background: #aef; margin: 0;">Заголовок</h2>

    <div>А тут - всякий разный текст... <br/>
         ... В две строки!</div>
</div>

Свойства left/top не будут работать для position:static. Если их все же поставить, браузер их проигнорирует. Эти свойства предназначены для работы только с позиционированными элементами.

position: absolute

Синтаксис:

position: absolute;

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

  1. Элемент исчезает с того места, где он должен быть и позиционируется заново. Остальные элементы, располагаются так, как будто этого элемента никогда не было.
  2. Координаты top/bottom/left/right для нового местоположения отсчитываются от ближайшего позиционированного родителя, т.е. родителя с позиционированием, отличным от static. Если такого родителя нет -- то относительно документа.

Кроме того:

Например, отпозиционируем заголовок в правом-верхнем углу документа:

*!*
<style>
  h2 {
    position: absolute;
    right: 0;
    top: 0;
  }
</style>
*/!*

<div style="background: #fee; width: 500px">
    Заголовок в правом-верхнем углу документа.

    <h2 style="background: #aef; margin: 0;">Заголовок</h2>

    <div>А тут - всякий разный текст... <br/>
         ... В две строки!</div>
</div>

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

Так как при position:absolute размер блока устанавливается по содержимому, то широкий Заголовок "съёжился" до прямоугольника в углу.

Иногда бывает нужно поменять элементу position на absolute, но так, чтобы элементы вокруг не сдвигались. Как правило это делают, меняя соседей -- добавляют margin/padding или вставляют в документ пустой элемент с такими же размерами.

````smart header="Одновременное указание left/right, `top/bottom`" В абсолютно позиционированном элементе можно одновременно задавать противоположные границы.

Браузер растянет такой элемент до границ.

<style>
*!*
div {
  position: absolute;
  left: 10px; right: 10px; top: 10px; bottom: 10px;
}
*/!*
</style>
<div style="background:#aef;text-align:center">10px от границ</div>

````smart header="Внешним блоком является окно"
Как растянуть абсолютно позиционированный блок на всю ширину документа?

Первое, что может прийти в голову:

```css
/*+ no-beautify */
div {
  position: absolute;
  left: 0; top: 0; /* в левый-верхний угол */
  width: 100%; height: 100%; /* .. и растянуть */
}
```

Но это будет работать лишь до тех пор, пока у страницы не появится скроллинг!

Прокрутите вниз ифрейм:

[iframe src="position-100-wrong" height=200 link]

**Вы увидите, что голубой фон оканчивается задолго до конца документа.**

Дело в том, что в CSS `100%` относится к ширине внешнего блока ("containing block"). А какой внешний блок имеется в виду здесь, ведь элемент изъят со своего обычного места?

В данном случае им является так называемый (["\"initial containing block\""](http://www.w3.org/TR/CSS21/visudet.html#containing-block-details)), которым является окно, *а не документ*.

**То есть, координаты и ширины вычисляются относительно окна, а не документа.**

Может быть, получится так?

```css
/*+ no-beautify */
div {
  position: absolute;
  left: 0; top: 0; /* в левый-верхний угол, и растянуть..  */
  right: 0; bottom: 0; /* ..указанием противоположных границ */
}
```

С виду логично, но нет, не получится!

Координаты `top/right/left/bottom` вычисляются относительно *окна*. Значение `bottom: 0` -- нижняя граница окна, а не документа, блок растянется до неё. То есть, будет то же самое, что и в предыдущем примере.

position: absolute в позиционированном родителе

Если у элемента есть позиционированный предок, то position: absolute работает относительно него, а не относительно документа.

То есть, достаточно поставить родительскому div позицию relative, даже без координат -- и заголовок будет в его правом-верхнем углу, вот так:

*!*
<style>
  h2 {
    position: absolute;
    right: 0;
    top: 0;
  }
</style>
*/!*

<div style="background: #fee; width: 500px; *!*position: relative*/!*">
    Заголовок в правом-верхнем углу DIV'а.

    <h2 style="background: #aef; margin: 0;">Заголовок</h2>

    <div>А тут - всякий разный текст... <br/>
         ... В две строки!</div>
</div>

Нужно пользоваться таким позиционированием с осторожностью, т.к оно может перекрыть текст. Этим оно отличается от float.

Сравните:

  • Используем position для размещения элемента управления:

    <button style="position: absolute; right: 10px; opacity: 0.8">
      Кнопка
    </button>
    1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9
    1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9

    Часть текста перекрывается. Кнопка более не участвует в потоке.

  • Используем float для размещения элемента управления:

    <button style="float: right; margin-right: 10px; opacity: 0.8;">
      Кнопка
    </button>
    1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9
    1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9

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

position: fixed

Это подвид абсолютного позиционирования.

Синтаксис:

position: fixed;

Позиционирует объект точно так же, как absolute, но относительно window.

Разница в нескольких словах:

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

В следующем примере, при прокрутке документа, ссылка #top всегда остается на своем месте.

<style>
*!*
  #top {
    position: fixed;
    right: 10px;
    top: 10px;
    background: #fee;
  }
*/!*
</style>

*!*<a href="#" id="top">Наверх (остается при прокрутке)</a>*/!*

Фиксированное позиционирование.

<p>Текст страницы.. Прокрути меня...</p>
<p>Много строк..</p><p>Много строк..</p>
<p>Много строк..</p><p>Много строк..</p>
<p>Много строк..</p><p>Много строк..</p>
<p>Много строк..</p><p>Много строк..</p>

Итого

Виды позиционирования и их особенности.

static : Иначе называется "без позиционирования". В явном виде задаётся только если надо переопределить другое правило CSS.

relative : Сдвигает элемент относительно текущего места.

  • Противоположные границы left/right (top/bottom) одновременно указать нельзя.
  • Окружающие элементы ведут себя так, как будто элемент не сдвигался.

absolute : Визуально переносит элемент на новое место.

Новое место вычисляется по координатам `left/top/right/bottom` относительно ближайшего позиционированного родителя. Если такого родителя нет, то им считается окно.
  • Ширина элемента по умолчанию устанавливается по содержимому.

  • Можно указать противоположные границы left/right (top/bottom). Элемент растянется.

  • Окружающие элементы заполняют освободившееся место.

fixed : Подвид абсолютного позиционирования, при котором элемент привязывается к координатам окна, а не документа.

При прокрутке он остаётся на том же месте.

Почитать

CSS-позиционирование по-настоящему глубоко в спецификации Visual Formatting Model, 9.3 и ниже.

Еще есть хорошее руководство CSS Positioning in 10 steps, которое охватывает основные типы позиционирования.