Обычное позиционирование 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 задаёт элементу абсолютное позиционирование.

Абсолютно спозиционированные элементы обладают следующими особенностями:

  1. Выпадают из потока документа. Место, которое они занимали, становится как бы пустым и его занимают соседние элементы.
  2. Ширина по умолчанию зависит от содержимого (а не растягивается на всю доступную ширину).
  3. Остаются на том же месте, где были, если не заданы значения свойств topleftrightbottom.

Абсолютное позиционирование изменяет поведение не только блочных элементов (ширина по умолчанию), но и строчных.

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

Можно сказать, что есть ещё один тип элементов — абсолютно спозиционированные. Такими становятся элементы всех остальных типов (блочные, строчные, блочно-строчные и так далее), если им задано свойство position: absolute;.

Свойства lefttopright и 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 задаёт элементу фиксированное позиционирование.

Фиксированное позиционирование похоже на абсолютное, но есть и отличия:

  1. Фиксированный элемент тоже выпадает из потока.
  2. Фиксированный элемент привязывается к определенной точке в окне браузера и остается на ней всегда, даже при прокрутке страницы.
  3. Фиксированный элемент можно позиционировать с помощью свойств topleftrightbottom, но точка отсчета всегда привязана к окну браузера.

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

z-index или кто кого перекроет

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

C помощью CSS-свойства z-index можно управлять тем, как перекрываются блоки. Значением этого свойства может быть целое число. Чем больше z-index, тем выше располагается блок.

Cвойство z-index работает для элементов, у которых position задано как absolutefixed и 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”:
    1. transform
    2. filter
    3. perspective
    4. clip-path
    5. 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 для дочерних элементов формирующих контекст наложения, будут учитываться только в рамках родительского элемента. Контекст наложения обрабатываются атомарно, как единое целое в контексте наложения родителя.