Перевод статьи «A painless guide to understanding CSS positioning».
Если вы хотите действительно хорошо овладеть CSS, очень важно разобраться в свойстве position
. Но стоит учесть, что для начинающих эта тема может быть довольно сложной.
Создавая свое портфолио, я обнаружил, что у меня нет понимания свойства position
. Я просто случайным образом применял различные комбинации значений, пока не достигал приемлемого для себя эффекта. Но по большей части все, что я писал, приходилось стирать.
В этой статье я постараюсь избавить вас от подобных мучений. Я расскажу о каждом из значений CSS-свойства position
и покажу, как они работают.
Но прежде чем приступить к разбору свойства position
и его значений, давайте остановимся на том, как элементы вообще располагаются на веб-страницах.
Поточная раскладка
То, как элементы отображаются на странице, называется нормальным потоком или поточной раскладкой. Это расположение элементов по умолчанию. Поток — это все элементы вашей страницы, «работающие» вместе и знающие о наличии остальных элементов.
CSS трактует каждый HTML-элемент как отдельный блок (возможно, вы слышали о понятии «блочная модель»). Элементы блочного уровня (заголовки, абзацы или блоки div
) по умолчанию начинаются как бы с новой строки. А строчные (inline) элементы (например, изображения и элементы span
), отображаются в строке вместе с другим контентом. Такое отображение элементов принято по умолчанию и называется нормальным потоком документа. Но CSS дает нам мощный инструмент для перезаписи нормального потока — свойство position
.
Давайте рассмотрим, что оно делает.
Свойство position
CSS-свойство position указывает, каким образом элемент должен позиционироваться в документе. Задавая значения этого свойства, мы можем определять местонахождение каждого отдельного элемента.
Свойство position
имеет пять возможных значений:
- static (статическое позиционирование)
- relative (относительное)
- absolute (абсолютное)
- fixed (фиксированное)
- sticky (липкое)
Мы разберем все 5 значений, но сначала обратим внимание на свойства расположения.
Свойства расположения
Само по себе свойство position
не слишком-то много и может. Чтобы указать, где именно в документе нужно расположить элемент, мы используем свойства расположения (это не официальное название, это я их так называю). Этих свойств четыре:
- top (верх)
- left (слева)
- right (справа)
- bottom (низ)
Значения этих свойств определяют, насколько позиция элемента должна сместиться и в каком направлении (вверх, вниз, влево, вправо). Чуть позже мы все это разберем на примерах.
Значения свойства position
Статическое позиционирование
static
— это дефолтное значение свойства position
. Оно предполагает, что элементы на странице отображаются в нормальном потоке. Свойства top
, left
, bottom
и right
не влияют на элемент, имеющий position: static
.
Несмотря на то, что это дефолтное значение, оно может задаваться явно. Например, когда вам нужно перезаписать значение position
, установленное где-то еще (и унаследованное вашим элементом).
Давайте рассмотрим пример. На нем мы увидим, что указание position: static
никак не влияет на отображение элемента.
<div class="parent-box"> <div class="box-original"> <div class="box-1"> </div> </div> <div class="box-original"> <div class="box-2"> </div> </div> <div class="box-original"> <div class="box-3"> </div> </div> </div>
Здесь у нас три блока div
, каждый из которых находится в родительском контейнере с классом box-original
.
Давайте добавим position: static
для div
с классом box-2
и зададим также значения для свойств top
и left
.
.box-2 { position: static; top: 10px; left: 10px; border: 1px solid black; background-color: mediumpurple; width: 100px; height: 100px; text-align: center; display: inline-block; align-self: center; margin-left: -1px; margin-top: -1px; }
Результат изменений:
See the Pen Static Positioning by Peter (@pin0s) on CodePen.
Как видите, несмотря на то, что мы задали свойства top
и left
, блок располагается в нормальном потоке.
Теперь вы знаете, что значение static
является дефолтным для свойства position
, а указание свойств расположения не сдвигает элементы, для которых указано position: static
.
Относительное позиционирование
Относительное позиционирование означает, что элемент позиционируется относительно своей исходной позиции в нормальном потоке. Если просто задать элементу position: relative
, ничего не произойдет. Для изменения позиции нужно задать свойства расположения.
В общем, если вы просто задаете элементу position: relative
, он остается в нормальном потоке. Но при помощи свойств расположения вы можете его сдвинуть. Давайте рассмотрим пример.
Возьмем код из прошлого примера и заменим position: static
на position: relative
.
.box-2 { position: relative; top: 10px; left: 10px; border: 1px solid red; background-color: mediumpurple; width: 100px; height: 100px; text-align: center; align-self: center; margin-left: -1px; margin-top: -1px; }
Результат:
See the Pen Relative Positioning by Peter (@pin0s) on CodePen.
Фиолетовый квадрат сдвинулся со своей нормальной позиции (обозначена серым квадратом). В этом примере задано смещение на 10px от верха и от левого края этого же элемента в дефолтном положении (т. е. смещение вниз и вправо).
Элемент при этом остается в нормальном потоке документа, а сдвиг происходит относительно его исходной позиции. Запомните это: пригодится, когда мы будем разбирать следующие значения.
Абсолютное позиционирование
При абсолютном позиционировании элементы изымаются из нормального потока документа, а пространство, которое они занимали, больше не резервируется за ними. То есть их как бы вообще здесь нет.
Когда элементу задано позиционирование position: absolute
, все остальные элементы ведут себя так, будто этого элемента вообще больше нет в документе. Поэтому для этого элемента не резервируется место поточной раскладке. Абсолютное позиционирование — мощный инструмент в деле перемещения элементов.
Когда я изучал это свойство, от меня кое-что ускользало, так что я считаю необходимым заострить ваше внимание. Элемент со свойством position: absolute позиционируется относительно своего ближайшего позиционированного предка. Это означает, что для того, чтобы абсолютное позиционирование сработало, родительский элемент должен иметь заданное значение свойства position
, причем не static
.
Это очень важный момент. Если ближайший родительский элемент не имеет указанного свойства position
, элемент с абсолютным позиционированием будет позиционироваться относительно следующего в иерархии родительского элемента, имеющего это свойство. Если у элемента вообще не будет позиционированных предков, он будет позиционироваться относительно элемента html
или viewport. Не зная этого, можно долго ломать голову, почему все работает не так, как задумано.
Элемент с абсолютным позиционированием можно перемещать как угодно. При помощи свойств top
, left
, bottom
и right
вы можете определить, где должен находиться этот элемент относительно его позиционированного предка (первого в иерархии среди имеющих значение position
, отличное от static
).
Вернемся к нашему примеру. Изменим свойство position второго блочного элемента на position: absolute
. Прежде чем рассматривать результат, вернитесь к предыдущему пену и обратите внимание на позиционирование элемента parent-box
.
.box-2 { position: absolute; top: 30px; left: 150px; border: 1px solid red; background-color: mediumpurple; width: 100px; height: 100px; text-align: center; align-self: center; margin-left: -1px; margin-top: -1px; }
Результат изменений:
See the Pen Absolute Positioning by Peter (@pin0s) on CodePen.
Вы видите, что в документе не создалось пустого места для нашего элемента. Фактически это место схлопнулось, и другие элементы ведут себя так, будто на этом месте вообще ничего никогда не было. Так происходит потому, что наш элемент теперь позиционируется относительно элемента parent-box
.
Фиксированное позиционирование
Фиксированное позиционирование работает подобно абсолютному. Оно удаляет элемент из нормального потока документа, причем под этот элемент в раскладке больше не отводится никакого места.
Элементы с фиксированным позиционированием позиционируются относительно viewport. (Viewport — это видимая пользователю область веб-страницы, то, что может увидеть пользователь, не прибегая к прокрутке, — MDN).
Это означает, что когда вы прокручиваете страницу, элемент остается на прежнем месте. Это часто используется при создании навигации на сайте: меню и т. п. блоки должны оставаться на месте, как бы пользователь ни прокручивал контент. Они остаются видимыми и доступными, например, вверху страницы.
Давайте изменим позиционирование box-2
с position: absolute
на position: fixed
. Также мы изменим значение свойства top
на 0 и удалим значение свойства left
. Еще мы добавим несколько дополнительных блоков, чтобы увидеть эффект при прокрутке.
.box-2 { position: fixed; top: 0px; border: 1px solid red; background-color: mediumpurple; width: 100px; height: 100px; text-align: center; align-self: center; margin-left: -1px; margin-top: -1px; }
Результат:
See the Pen Fixed Positioning by Peter (@pin0s) on CodePen.
Как видите, фиолетовый блок теперь зафиксирован вверху страницы. Мы добились такого эффекта, установив для него position: fixed
и top: 0px
.
При использовании position: fixed
важно помнить, что элемент будет постоянно занимать какое-то место в зоне просмотра. Это может негативно сказаться на пользовательском опыте, особенно на мобильных устройствах, где пространство ограничено. Так что обдумывайте, как все будет выглядеть на разных устройствах.
Липкое позиционирование
Липкое позиционирование — это позиционирование согласно нормального потока документа, но также это смесь относительного и фиксированного позиционирования. Я имею в виду, что элемент ведет себя как относительно позиционированный, пока страница при прокрутке не достигает заданной точки — и тогда элемент начинает вести себя, как элемент с фиксированной позицией.
Давайте рассмотрим новый пример. Мы зададим dt
свойство position: sticky
и top: 3px
(т. е. смещение на 3px от верха страницы).
dt { background: #007FFF; border-bottom: 1px solid yellow; border-top: 1px solid yellow; color: yellow; margin: 0; padding: 2px 0 0 12px; position: sticky; top: 3px; }
Попробуйте прокрутить страницу, и увидите, как работает липкое позиционирование.
See the Pen Sticky Positioning by Peter (@pin0s) on CodePen.
Вы видите, что элементы dt
(голубые строки) прилипают к верху страницы до тех пор, пока мы не прокрутим контент до следующего элемента dt
. При достижении этой точки липким элементом становится следующий dt
. Таким образом, элементы dt
позиционированы в нормальном потоке страницы, но когда они достигают определенного места при прокрутке, их позиционирование меняется на фиксированное. Они закрепляются на этой позиции, пока вы не прокрутите до следующего элемента dt
, который приобретет фиксированное позиционирование.
Работать с липким позиционированием надо осторожно, потому что не все браузеры его поддерживают (по крайней мере, на момент написания статьи). Проверить поддержку можно при помощи caniuse.com.
Где во всем этом место Z-индекса?
z-index
— это CSS-свойство, позволяющее задавать порядок позиционированных элементов по оси z. Любой элемент, которому вы задали свойство position
, отличное от static
, может позиционироваться и по оси z.
В целом, z-index
позволяет контролировать порядок расположения и, таким образом, перекрытие элементов. С его помощью вы определяете, какие элементы должны стоять на переднем плане, а какие — сзади.
Элементы с большим значением z-index
отображаются перед элементами с меньшими значениями.
Рассмотрим пример. Я покажу, что при использовании z-index
порядок элементов в html-разметке не имеет значения, мы можем сменить их позицию с передней на заднюю.
<div class="parent-box"> <div class="box box-1">z-index:4</div> <div class="box box-2">z-index:1</div> <div class="box box-3">z-index:2</div> <div class="box box-4">z-index:5</div> <div class="box box-5">z-index:3</div> </div>
Мы зададим каждому классу box
позицию fixed
, что позволит нам изменить z-index
каждого из box
-элементов.
Результат:
See the Pen Z-index by Peter (@pin0s) on CodePen.
Как видите, элементы с более высоким значением z-index
идут на переднем плане, а с более низким — на заднем.
Заключение
Давайте подобьем итоги. CSS-свойство position
— очень мощный инструмент, позволяющий определять, где именно на странице должны находиться те или иные элементы, и таким образом изменять нормальный поток документа.
Мы можем применять пять значений свойства position
:
- static
- relative
- absolute
- fixed
- sticky
Положение элемента задается при помощи свойств top
, left
, bottom
и right
. Значения этих свойств указывают, насколько должен сместиться элемент от указанной точки.
Если элемент позиционирован, причем значение position
— не static
, можно задавать положение этого элемента по оси z. Это делается при помощи свойства z-index
. Чем выше значение этого свойства, тем ближе к переднему плану выводится элемент. Элементы с более низкими значениями z-index
выводятся на заднем плане.
Самый лучший способ разобраться в CSS-свойстве position
— поиграться с ним. Возьмите пены, приведенные здесь в качестве примеров, попробуйте поменять в них какие-нибудь значения и посмотрите, к чему это приведет.
[customscript]techrocks_custom_after_post_html[/customscript]
[customscript]techrocks_custom_script[/customscript]