Обычное позиционирование position: static
CSS-свойство position задает режим позиционирования элементов.
Значением по умолчанию является static, которое означает «обычное позиционирование».
Относительное позиционирование position: relative
Значение relative обозначает «относительное позиционирование». Относительно спозиционированный элемент можно перемещать относительно его исходного положения.
Относительно спозиционированный элемент остается в потоке документа, а при его перемещении наблюдаются интересные эффекты. Для начала просто зададим относительное позиционирование выбранному блоку.
position: relative и свойство top
Свойство top
позволяет сместить относительно спозиционированный элемент вверх или вниз относительно его исходного положения.
position: relative и свойство left
Свойство left
позволяет сместить блок влево или вправо относительно исходного положения.
Значение этого свойства обычно задается в пикселях, но можно использовать и другие единицы измерения CSS.
position: relative и свойство bottom
Свойство bottom
аналогично свойству top
, только смещает элемент в другом направлении.
Положительное значение свойства bottom
сместит элемент вверх, а отрицательное вниз.
position: relative и свойство right
Свойство right
аналогично свойству left
и тоже смещает элемент в другом направлении.
Абсолютное позиционирование position: absolute
Значение absolute
свойства position
задаёт элементу абсолютное позиционирование.
Абсолютно спозиционированные элементы обладают следующими особенностями:
- Выпадают из потока документа. Место, которое они занимали, становится как бы пустым и его занимают соседние элементы.
- Ширина по умолчанию зависит от содержимого (а не растягивается на всю доступную ширину).
- Остаются на том же месте, где были, если не заданы значения свойств
top
,left
,right
,bottom
.
Абсолютное позиционирование изменяет поведение не только блочных элементов (ширина по умолчанию), но и строчных.
Если строчный элемент спозиционирован абсолютно, то он ведет себя точно так же, как и абсолютно спозиционированный блочный.
Например, такому строчному элементу можно задавать размеры с помощью width
и height
.
Можно сказать, что есть ещё один тип элементов — абсолютно спозиционированные. Такими становятся элементы всех остальных типов (блочные, строчные, блочно-строчные и так далее), если им задано свойство position: absolute;
.
Свойства left
, top
, right
и bottom
по-разному работают для элементов с абсолютным и относительным позиционированием.
Если для «относительных» элементов эти свойства задают смещение относительно исходной позиции, то для «абсолютных» элементов они задают расположение относительно некой системы координат, как для точки на графике.
По умолчанию такой системой координат является окно браузера, а точки начала координат привязаны к его углам.
position: absolute и свойство left
Свойство left
задает отступ от левого края окна браузера до левого края абсолютно спозиционированного элемента. Если свойству задать отрицательное значение, то элемент сместится за левый край браузера (при этом полоса прокрутки не появится).
position: absolute и свойство top
Свойство top
задает отступ от верхнего края окна браузера до верхнего края абсолютно спозиционированного элемента.
position: absolute и свойство right
Свойство right
задает отступ от правого края окна браузера до правого края «абсолютного» элемента.
Это свойство позволяет легко прижать элемент любой ширины к правому краю окна. Если задать отрицательное значение для right
, то элемент сместится за край окна, но при этом появится полоса прокрутки.
C помощью top
+ right
можно позиционировать элементы от правого верхнего угла.
position: absolute и свойство bottom
Свойство bottom
задает отступ от нижнего края окна браузера до нижнего края «абсолютного» элемента.
В связи с особенностями нашего мини-браузера к свойству bottom добавляется дополнительный отступ, которого в обычных браузерах нет.
Отрицательное значение bottom
затолкнет элемент за нижний край окна браузера и при этом появится полоса прокрутки.
Точка отсчёта координат
По умолчанию «абсолютные» элементы позиционируются в системе координат, привязанной к окну браузера. Однако, систему координат можно изменить.
Если какой-нибудь из родителей «абсолютного» элемента имеет относительное позиционирование, то элемент будет позиционироваться относительно этого родителя. Если среди родителей несколько относительно позиционированных элементов, то «абсолютный» элемент будет позиционироваться относительно ближайшего из них.
В этом задании вы увидите, как происходит смена системы координат (и соответственно точек отсчета). Интересно, что позиционирование по умолчанию отличается от позиционирования внутри тега body
.
Неявная точка отсчёта
Неявная точка отсчета — это то место, где находился элемент до того, как ему задали абсолютное позиционирование. Если «абсолютному» элементу не задавать свойства left
… bottom
, то он выпадет из потока, но останется на прежнем месте.
Такой элемент можно сместить из неявной точки отсчета с помощью свойства margin
. Оно будет работать примерно так же, как и свойства left
… bottom
для «относительного» элемента.
Кстати, когда значение для left
не задано, оно равно auto
. То же верно и для оставшихся трёх свойств. С помощью значения auto
можно возвращать «абсолютные» элементы на исходное положение.
Фиксированное позиционирование position: fixed
Значение fixed
свойства position
задаёт элементу фиксированное позиционирование.
Фиксированное позиционирование похоже на абсолютное, но есть и отличия:
- Фиксированный элемент тоже выпадает из потока.
- Фиксированный элемент привязывается к определенной точке в окне браузера и остается на ней всегда, даже при прокрутке страницы.
- Фиксированный элемент можно позиционировать с помощью свойств
top
,left
,right
,bottom
, но точка отсчета всегда привязана к окну браузера.
Можете представить себе фиксированный элемент, как стикер, который наклеен на монитор. Такие элементы часто применяют для создания навигационных панелей, привязанных к верхней или нижней части окна браузера.
z-index или кто кого перекроет
Если в одном месте страницы оказываются несколько «абсолютных» блоков, то они перекрывают друг друга. По умолчанию выше оказывается тот блок, который расположен дальше в коде страницы.
C помощью CSS-свойства z-index
можно управлять тем, как перекрываются блоки. Значением этого свойства может быть целое число. Чем больше z-index
, тем выше располагается блок.
Cвойство z-index
работает для элементов, у которых position
задано как absolute
, fixed
и relative
. Таким образом, «относительный» элемент может перекрывать «абсолютный».
Контекст наложения
Контекст наложения (stacking context) это концепция трёхмерного расположения HTML-элементов вдоль оси Z по отношению к пользователю, находящемуся перед экраном. HTML-элементы занимают это место по порядку, основанному на атрибутах элемента.
Практически полностью отсутствует информация на данную тему. И когда в ходе собственных экспериментов при обучении я столкнулся с данной проблемой, ушло немало времени, чтобы понять, как всё это работает. На Хабре есть статья 37, еще от 13-года на эту тему, но там не совсем удачный, на мой взгляд, пример. Да и вариантов “странного поведения”, как оказалось, намного больше, чем указано в данной статье. В любом случае, идея была взята там на 90%, как и некоторые цитаты.
И да, если у вас браузер исключительно от Microsoft, дальше можно не читать. Они там ничего про это знать не хотят.
И так, напишем небольшой и легко читаемый код:
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Контекст наложения</title>
<meta charset="utf-8">
<style>
div:nth-child(2) {
opacity: .99;
}
.red, .green, .blue {
width: 200px;
height: 200px;
position: absolute;
}
.red {
background: red;
top: 0;
left: 0;
z-index: 1;
}
.green {
background: green;
top: 100px;
left: 100px;
z-index: 10;
}
.blue {
background: blue;
top: 150px;
left: 150px;
}
.yellow {
background: yellow;
top: 0px;
left: 0px;
width: 250px;
height: 250px;
position: absolute;
}
body {
background: black;
}
</style>
</head>
<body>
<div><span class="red"></span><span class="yellow"></span></div>
<div><span class="green"></span></div>
<div><span class="blue"></span></div>
</body>
</html>
Внимание, вопрос: какой элемент перекроет остальные?
“Зелёный! Ведь он имеет наибольший z-index”, - скорее всего, скажете вы.
Точно? Вы уверены? Проверьте код, и вы поймёте, что ошиблись.
Верный ответ намного интереснее. Сверху окажется красный!
Почему так? Всё дело в контексте наложения.
Контекст наложения представляет собой трехмерное расположение html-элементов вдоль воображаемой оси z относительно пользователя. Элементы html занимают это пространство в порядке приоритета на основе атрибутов элемента.
В момент формирования нового контекста на элементе, все дочерние элементы так же попадают в этот контекст и занимают своё место в порядке наложения.
Если элемент располагается в самом низу одного контекста наложения, то никаким мыслимым и немыслимым образом не получится отобразить его над другим элементом в соседнем контексте наложения, располагающимся выше по иерархии, даже с установленным z-index равным миллиону.
Новый контекст наложения формируется в любом месте документа любым элементом в следующих сценариях:
- является корневым элементом документа (HTML);
- для элемента position задано как “absolute” или “relative” и z-index отличен от “auto”;
- для элемента position задано как “fixed” или “sticky” (для мобильных браузеров);
- элемент является дочерним для flex (flexbox) контейнера и z-index отличен от “auto”;
- элемент с opacity меньше 1 ;
- элемент со значением mix-blend-mode отличным от “normal”;
- элемент со значением isolation равным “isolate”;
- элемент со значением -webkit-overflow-scrolling равным “touch”.
- элемент с одним из следующий свойств, имеющих значение отличное от “none”:
- transform
- filter
- perspective
- clip-path
- mask / mask-image / mask-border
- элемент со значением will-change, которое создаст новый контекст наложения.
Некоторые другие наглядные примеры (на английском языке) можно посмотреть здесь 74.
Хотя в душе я, наверное, солидарен с разработчиками из Microsoft. Лучше бы это было багом, а не спецификацией. Писать код было бы проще, не думая от таких особенностях.
Контекст наложения v. 2 stacking context
Контекст наложения (stacking context) это концепция трёхмерного расположения HTML-элементов вдоль оси Z по отношению к пользователю, находящемуся перед экраном. HTML-элементы занимают это место по порядку, основанному на атрибутах элемента.
Контекст может формироваться в любом месте документа, любым элементом, у которого выполняется одно из следующих условий:
- является корневым элементом (HTML),
- позиционирован абсолютно (position:absolute) или относительно (position:relative) с z-index значением отличным от “auto”,
- flex элемент с z-index отличным от “auto”, чей родительский элемент имеет свойство display: flex|inline-flex,
- элементы с
opacity
меньше чем 1. (См. the specification for opacity), - элементы с
transform
отличным от “none”, - элементы с
mix-blend-mode
значением отличным от “normal”, - элементы с
filter
значением отличным от “none”, - элементы с
isolation
установленным в “isolate”, position: fixed
- если мы указываем элементу атрибут
[`will-change`](https://developer.mozilla.org/ru/docs/Web/CSS/will-change)
при этом не обязательно присваивать ему значения (См. this post) - элементы с
-webkit-overflow-scrolling
(en-US) установленным в “touch”
Внутри контекста наложения дочерние элементы расположены в соответствии с правилами, описанными ранее. Важно заметить, что значения свойства z-index для дочерних элементов формирующих контекст наложения, будут учитываться только в рамках родительского элемента. Контекст наложения обрабатываются атомарно, как единое целое в контексте наложения родителя.