Позиционирование - position

Позиционирование позволяет "вынимать" элемент из нормального потока документа и вести себя по-другому; управлять расположением (позицией) элемента на странице. Например, используя позиционирование, можно поместить и закрепить навигационную панель наверху страницы, даже когда пользователи прокручивают страницу вниз.

Позиционирование задается с помощью CSS-свойства position.

Свойство position имеет 5 значений:
  • static (статичное позиционирование);
  • relative (относительное);
  • absolute (абсолютное);
  • fixed (фиксированное);
  • sticky (липкое).

Значением по умолчанию является static, которое означает «обычное позиционирование» - означает, что элемент находится в нормальном потоке.
Относительное позиционирование - relative
Каждый элемент в потоке занимает определённую область. Но область элемента не всегда сохраняется за ним при его позиционировании.

Значение relative обозначает «относительное позиционирование».
Такой элемент перемещается относительно от его исходного положения, но все еще занимает свое место в потоке. Представьте покупателя, который перед вами оставил свою тележку со словами "я скоро подойду, не занимайте мое место" и отошел за забытым молоком. Сейчас переместился относительно своей очереди на кассу в отдел молочных продуктов, но формально он все еще в очереди. Также работает и relative со своими элементами.

Синтаксис:
position: relative;
После свойства position указываются свойства задающие смещение элемента на нужную вам позицию:
left, top, right и bottom.

Синтаксис:
top: 100px;
left: 100px;
right: 100px;
bottom: 100px;
Свойство top позволяет сместить относительно спозиционированный элемент вверх или вниз относительно его исходного положения. Значение этого свойства обычно задается в пикселях, но можно использовать и другие единицы измерения CSS.

Например, у нас есть три блока.
Блок 2 мы хотим сдвинуть вверх. Тогда зададим значение top: -35px.
.block-2 { 
  position: relative;
  top: -35px;
}
Теперь сдвинем блок 2 вниз, поменяв значение на top: 100px;
.block-2 { 
  position: relative;
  top: 100px;
}
Отрицательное значение сдвигает элемент вверх, положительное вниз.

Заметили, что когда мы сместили блок вверх, другие два блока не сдвинулись?
На примере мы убедились в том, что относительно спозиционированный элемент на самом деле никуда не смещается. Он остаётся в потоке ровно там же, где и был (это место обозначено серым блоком-тенью). А смещается иллюзорная копия блока.

Свойство bottom аналогично свойству top, только смещает элемент в другом направлении.
Положительное значение свойства bottom сместит элемент вверх, а отрицательное вниз.
Свойство left позволяет сместить блок влево или вправо относительно исходного положения.
Положительное значение сдвигает элемент вправо, отрицательное - влево.

Рассмотрим на том же примере с блоками.
Зададим значение left: 100px, тем самым сдвинув его вправо.
.block-2 { 
  position: relative;
  left: 100px; /*элемент сдвинется вправо*/
}
Затем установим значение на -100px, тем самым двигая элемент влево.
.block-2 { 
  position: relative;
  left: -100px; /*элемент сдвинется влево*/
}
Последнее свойство right аналогично свойству left и тоже смещает элемент в другом направлении.
Положительное значение сдвинет элемент влево, отрицательное - вправо.

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

В реальных проектах относительное позиционирование может использоваться для создания декоративных эффектов, например, тень для элемента.
Абсолютное позиционирование - absolute
Значение absolute задаёт элементу "абсолютное позиционирование".

Абсолютное позиционирование выполняется немного по-другому и элементы в нем обладают следующими особенностями:
  1. Элементы полностью удаляются из потока документа. Место, которое они занимали, становится как бы пустым и его занимают соседние элементы. Если сравнить с примерами очередей в супермаркете, то вы будто освобождаете место в очереди и уходите на другую кассу, а стоящий за вами человек занимает ваше место.
  2. Ширина по умолчанию зависит от содержимого (а не растягивается на всю доступную ширину).
  3. Остаются на том же месте, где были, если не заданы значения свойств top, left, right, bottom.

Синтаксис:
position: absolute;

/*Дальше указывается позиция элемента с помощью*/
left: 100px; 
right: 100px;
top: 100px;
bottom: 100px;
Абсолютное позиционирование меняет поведение как блочных элементов, так и строчных.
Условно можно сказать, что асолютно спозиционированные элементы - это еще один тип элементов. Им становятся элементы всех остальных типов блочные, строчные, блочно-строчные и так далее, если задано свойство position: absolute.

Таким элементам можно задавать размеры с помощью width и heigth.

Рассмотрим на примере тех же 3 блоков.
Зададим блоку 2 абсолютную позицию.
  <body>
    <div class="block-1">Блок 1</div>
    <div class="block-2">Блок 2</div>
    <div class="block-3">Блок 3</div>
  </body>
body {
  padding: 20px;
  border: 1px dotted #999999;
}

/*Блок 1*/
.block-1 {
  padding: 15px;
  margin-bottom: 20px;
  color: white;
  background-color: #4477bb;
}

/*Блок 2, которому задано абсолютное позиционирование*/
.block-2 {
  position: absolute; /*абсолютное позиционирование*/
  margin-bottom: 20px; /*Внешний отступ от блока*/
  padding: 15px; /*Внутренний отступ от текста*/
  color: white;
  background-color: #114488;
}

/*Блок 3*/
.block-3 {
  padding: 15px;
  margin-bottom: 20px;
  color: white;
  background-color: #4477bb;
}
Как вы можете видеть, пространство, когда-то занимаемое блоком 2, теперь сомкнуто. Так будет происходить со всеми абсолютно позиционированными элементами.

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

Давайте сравним два слайдера с одинаковыми параметрами, но разным указанием позиционирования.
Первый слайд - относительное, второй - абсолютное.
/*Первый слайд*/
.block-2 { 
  position: relative;
  left: 29px;
  top: 165px;
  width: 1460px;
}

/*Второй слайд*/
.block-2 {
  position: absolute;
  left: 29px;
  top: 165px;
  width: 1460px;
}
Что произошло?
Если для «относительных» элементов эти свойства задают смещение относительно исходной позиции, то для «абсолютных» элементов они задают расположение относительно некой системы координат, как для точки на графике.

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

Существует принцип содержащего блока элемента, который вы хотите разместить. Иногда его называют контекстом позиционирования.
Два простых правила содержащего блока:
- Если позиционированный элемент не содержится внутри другого позиционированного элемента, тогда он будет размещен относительно начального содержащего блока (созданного элементом html).
- Если элемент имеет «предка» (то есть содержится внутри другого элемента), который имеет положение, установленное в relative, absolute или fixed, он вместо этого будет позиционирован относительно краев того элемента.

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

В нашем примере выше, содержащим блоком является элемент <html>, т.к. у него нет предка, поэтому относительно него располагается блок 2.

Давайте рассмотрим другой пример, где мы каждому элементу будем добавлять position:relative.
<!DOCTYPE html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>position</title>
    <link href="style.css" rel="stylesheet">
  </head>
  <body>
    <div class="block-1">Блок 1
      <div class="block-2">Блок 2
        <div class="block-3">
          Блок 3 <br>
          position: absolute;<br>
          right: 0px;<br>
          top: 0px;
        </div>
      </div>
    </div>
  </body>
</html>
body {
  padding: 20px;
  border: 1px dotted #999999;
}

.block-1 {
  min-height: 150px;
  padding: 15px;
  color: white;
  background-color: #4B77BE;
}

.block-2 {
  position: relative; 
  margin-bottom: 20px; 
  padding: 15px; 
  min-height: 150px;
  color: white;
  background-color: #59ABE3;
}

.block-3 {
  position: absolute;
  top: 0px;
  right: 0px;
  padding: 10px;
  margin-bottom: 20px;
  padding: 10px;
  color: white;
  background-color: #1F4788;
  opacity: 0.8;
}
Сейчас содержащим блоком является элемент <html> , поэтому блок 3 расположится относительно него, так как нет другого позиционного элемента-родителя.
Сейчас блок 3 находится в правом верхнем углу.
Теперь зададим <body> относительную позицию.
body {
  position: relative; /*добавили относительно позиционирование body*/
  padding: 20px;
  border: 1px dotted #999999;
}

/*У блока 3 все еще абсолютное позиционирование*/
.block-3 {
  position: absolute;
  top: 10px;
  right: 10px;
  padding: 10px;
  margin-bottom: 20px;
  padding: 10px;
  color: white;
  background-color: #1F4788;
  opacity: 0.8;
}
У блока 3 появился родитель - body, поэтому блок 3 занял правую верхнюю позицию, но уже относительно него (мы специально пометили body пунктирной линией).
Теперь зададим относительную позицию блоку 1.
.block-1 {
  position: relative; /*добавили относительное позиционирование*/
  min-height: 150px;
  padding: 15px;
  color: white;
  background-color: #4B77BE;
}

/*У блока 3 все еще абсолютное позиционирование*/
.block-3 {
  position: absolute;
  top: 10px;
  right: 10px;
  padding: 10px;
  margin-bottom: 20px;
  padding: 10px;
  color: white;
  background-color: #1F4788;
  opacity: 0.8;
}
Мы видим, что блок 3 отказался от body и убежал к блоку 1. Теперь блок 1 новый родитель блока 3.
И последнее, зададим блоку 2 относительное позиционирование. Думаю вы уже должны догадаться что произойдет.
.block-2 {
  position: relative; /*теперь добавили относительное позиционирование блоку 2*/
  margin-bottom: 20px;
  padding: 15px;
  min-height: 150px;
  color: white;
  background-color: #59ABE3;
}

/*У блока 3 все еще абсолютное позиционирование*/
.block-3 {
  position: absolute;
  top: 10px;
  right: 10px;
  padding: 10px;
  margin-bottom: 20px;
  padding: 10px;
  color: white;
  background-color: #1F4788;
  opacity: 0.8;
}
Теперь, когда вы лучше понимаете принцип содержащего блока, давайте лучше познакомимся со свойствами смещения. До сих пор мы видели только перемещение элемента на несколько пикселов вниз и вправо, но это, конечно же, не все, что вы можете делать.

Мы уже писали, что когда элементу устанавливаем position: absolute без указания CSS-свойств ( top, left, right и bottom), то он выпадет из потока, но останется на прежнем месте.
Такой элемент можно сместить с помощью свойства margin. Оно будет работать примерно так же, как и свойства left … bottom для «относительного» элемента.

Если значение для left не задано, оно равно auto. То же верно и для оставшихся трёх свойств. С помощью значения auto можно возвращать «абсолютные» элементы на исходное положение.

На практике абсолютное позиционирование часто применяют в декоративных целях, когда нужно аккуратно разместить какие-либо иконки, управляющие элементы или другие «рюшечки».
Фиксированное позиционирование - fixed
Значение fixed свойства position задаёт элементу фиксированное позиционирование.

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

  1. Фиксированный элемент тоже выпадает из потока.
  2. Ширина также по умолчанию зависит от содержимого (а не растягивается на всю доступную ширину).
  3. Фиксированный элемент привязывается к определенной точке в окне браузера и остается на ней всегда, даже при прокрутке страницы.
  4. Фиксированный элемент можно позиционировать с помощью свойств top, left, right, bottom.
Можете представить себе фиксированный элемент, как стикер, который наклеен на монитор. Такие элементы часто применяют для создания навигационных панелей, привязанных к верхней или нижней части окна браузера.

Давайте вернемся к нашим знакомым блокам. Зададим блоку 1 фиксированную позицию.
<body>
    <div class="block-1">Блок 1</div>
      <div class="block-shadow">
        <div class="block-2">Блок 2</div>
      </div>
    <div class="block-3">Блок 3</div>
  </body>
.block-1 {
  position: fixed; /*фиксированная позиция*/
  min-height: 100px;
  padding: 15px;
  margin-bottom: 20px;
  color: white;
  background-color: #4477bb;
}
Мы видим, что блок сжался до уровня содержимого, но уже можно прокрутить страничку и посмотреть, что блок не двигается с места. Дальше с блоком можно работать как угодно - задать высоту-ширину, подвинуть вправо-лево-верх-низ и т.д. (второй слайд)
Липкое позиционирование - sticky
Значение sticky свойства position задаёт элементу "липкое" позиционирование.
По сути, это гибрид относительной и фиксированной позиции, который позволяет позиционируемому элементу вести себя как будто он относительно позиционирован, до тех пор пока он не будет прокручен до определённой указанной точки (например, 10px от вершины окна просмотра), после чего он становится фиксированным.

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

Итак, давайте разбиться как работает липкое позиционирование и как избежать проблем залипанием.
Если position: sticky является единственным ребёнком своего родителя-обёртки, то этот «липкий» элемент не залипает.
<!-- НЕ РАБОТАЕТ!!! -->
<style>
  .sticky {
    position: sticky;
    top: 0;
  }
</style>

<div class="wrapper">
  <div class="sticky">
     Некий контент
  </div>
</div>
«Липкое» позиционирование состоит из двух основных частей: «липкого» элемента и «липкого» контейнера.
«Липкий» элемент — это элемент, которому мы задали position: sticky. Элемент будет становиться плавающим, как только область видимости достигнет определённой позиции, например top: 0px.
«Липкий» контейнер — это HTML-элемент, который оборачивает «липкий» элемент. Это максимальная область, в которой может перемещаться наш элемент.

Когда вы задаёте элементу position: sticky , его родитель автоматически становится «липким» контейнером.
Очень важно это запомнить! Контейнер будет являться областью видимости для элемента. «Липкий» элемент не может выйти за пределы своего «липкого» контейнера.

В этом причина, почему в предыдущем примере «липкий» элемент не залипал: он был единственным дочерним элементом контейнера.

Добавим к нашим блокам маркированный список и блокам 1 и 2 зададим липкую позицию и поставим ее в верх экрана.
Скопируйте, пожалуйста, код к себе в VisualStudio и откройте файл через браузер.
<!DOCTYPE html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>position</title>
    <link href="style.css" rel="stylesheet">
  </head>
  <body>
    <div class="block-1">Блок 1</div>
    <ul> Продукты на "А"
      <li>апельсин</li>
      <li>абрикос</li>
      <li>авокадо</li>
    </ul>
    <div class="block-2">Блок 2</div>
    <ul> Продукты на "Б"
      <li>багет</li>
      <li>баклажан</li>
      <li>банан</li>
      </ul>
    <div class="block-3">Блок 3</div>
    <ul> Продукты на "В"
      <li>васаби</li>
      <li>ваниль</li>
      <li>варенье</li>
    </ul>
  </body>
</html>
body {
  min-height: 250px;
  padding: 20px;
  border: 1px dotted #999999;
}

h3{
  margin: 0;
  margin-bottom: 20px;
}

.block-1 {
  position: sticky; /*липкое позиционирование*/
  top: 0px; /*указываем что прокручиваться он начнет при попадании на экран от 0 пикселей*/
  min-height: 10px;
  padding: 15px;
  margin-bottom: 20px;
  color: white;
  background-color: #4477bb;
}

.block-2 {
  position: sticky; /*липкое позиционирование*/
  top: 0px;  /*указываем что прокручиваться он начнет при попадании на экран от 0 пикселей*/
  min-height: 10px;
  margin-bottom: 20px; /*Внешний отступ от блока*/
  padding: 15px; /*Внутренний отступ от текста*/
  color: white;
  background-color: #114488;
}

.block-3 {
  min-height: 10px;
  padding: 15px;
  margin-bottom: 20px;
  color: white;
  background-color: #4477bb;
}

ul {
  margin-bottom: 350px;
}


Это интересно.
position: sticky ведёт себя не так, как другие типы позиционирования.
Но у них есть определённые сходства со всеми сразу:

Относительное (или статичное) — «липкий» элемент похож на элемент со статическим или относительным позиционированием поскольку сохраняет свою естественную позицию в DOM (остаётся в потоке).

Фиксированное - когда элемент залипает, то ведёт себя как будто у него заданы стили position: fixed, остаётся на той же позиции в области видимости и вырывается из потока документа.

Абсолютное - в конце доступной для перемещений области элемент останавливается и остаётся поверх другого элемента. Точно также, как ведёт себя абсолютно спозиционированный элемент в контейнере с position: relative.
Перекрывающие элементы - свойство z-index
Если в одном месте страницы оказываются несколько абсолютных блоков, то они перекрывают друг друга. По умолчанию выше оказывается тот блок, который расположен дальше в коде страницы.

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

Cвойство z-index работает для элементов, у которых position задано как absolute, fixed, relative и sticky. Таким образом, «относительный» элемент может перекрывать «абсолютный».

Важно!
z-индекс работает только с позиционируемыми элементами!

Если указано position: static - такой элемент является не позиционированным.
Синтаксис
/* Ключевое слово */
z-index: auto;

/* Значения типа <integer> */
z-index: 0;
z-index: 3;
z-index: 289;
z-index: -1; /* Отрицательные значения понижают приоритет */

/* Глобальные значения */
z-index: inherit;
z-index: initial;
z-index: revert;
z-index: revert-layer;
z-index: unset;
Значения

auto
Элемент не будет создавать нового локального контекста наложения. Порядок наложения блока в текущим контексте наложения будет равен 0.

<integer>
Порядок наложения блока, заданный в виде целого числа в текущем контексте наложения. При этом элемент создаёт новый локальный контекст наложения. Таким образом значения z-index дочерних элементов внутри нового контекста наложения не будут сравниваться со значениями z-index элементов за пределами этого блока.

Рассмотрим на примере.
Допустим, у нас есть три блока. Сейчас они идут ровано в том порядке, в котором мы указали их позиционированием.
<!DOCTYPE html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>z-index</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <div class="block block-1">Блок 1</div>
    <div class="block block-2">Блок 2</div>
    <div class="block block-3">Блок 3</div>
  </body>
</html>
body {
  margin: 0;
  padding: 20px;
}

.block {
  padding: 10px;
  text-align: right;
  color: white;
  opacity: 0.8;
}

.block-1 {
  width: 350px;
  height: 350px;
  background-color: #4B77BE;
}

.block-2 {
  position: absolute;
  top: 20px;
  width: 250px;
  height: 250px;
  background-color: #59ABE3;
}

.block-3 {
  position: absolute;
  top: 20px;
  width: 150px;
  height: 150px;
  background-color: #1F4788;
}
Зададим блоку 2 значение z-index 10.
.block-2 {
  z-index: 10;
  position: absolute;
  top: 20px;
  width: 250px;
  height: 250px;
  background-color: #59ABE3;
}
Блок 2 перекрыл блок 3.
Давайте теперь зададим блоку 1 значение z-index 20.
.block-1 {
  z-index: 20;
  width: 350px;
  height: 350px;
  background-color: #4B77BE;
}
Мы видим, что ничего не произошло. Посмотрите внимательно на код и подумайте что с ним не так?
Если вы сразу увидели ошибку, молодцы!
Ничего не сработало, потому что у блока 1 не задано никакого позиционирования, а как мы уже говорили, z-index работает только с позиционируемыми элементами.
Давайте зададим блоку 1 относительное позиционирование.
.block-1 {
  position: relative;
  z-index: 20;
  width: 350px;
  height: 350px;
  background-color: #4B77BE;
}
Все сработало. Это базовые понятия z-index.
Но у него есть свои подводные камни.
Контекст наложения
Когда мы объясняли значения мы вскольз упомянули контекст наложения. Что же это такое? Давайте разбираться.

Браузер при отрисовке страницы идёт сверху вниз по HTML-разметке и рисует блоки один за другим в том же порядке, в котором они расположены. Мы видим и воспринимаем это как плоский лист, на котором один за другим выстраиваются элементы. Но на самом деле браузер располагает элементы не только по осям x и y, но ещё и по оси z, то есть по глубине.

Зачем это все? Браузеру важно учитывать глубину элементов, чтобы при необходимости правильно наложить их друг на друга. В стандартной ситуации тот элемент, который находится ниже в HTML-разметке будет ближе к пользователю.


Самый базовый контекст наложения, существующий на любой странице формируется корневым элементом <html>.Для простоты понимания, представим, что наш корневой элемент <html> - это самая большая коробка, в которую будут складываться другие коробочки поменьше - элементы. При упаковке эти коробки могут быть уже упакованы и закрыты, а могет быть открыты.
Если коробка закрыта, то внутренние коробки не могут выйти за пределы этой коробки. Закрытая коробка - это и есть контекст наложения.

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

Новый контекст наложения формируется (то есть коробка закрывается) если:
  1. Элемент является корневым ( <html>)
  2. Элемент имеет свойство position со значением relative или absolute и свойством z-index со значением, отличным от auto - то есть, с целочисленным значением
  3. Элемент имеет свойство position со значением sticky или fixed
  4. Элемент является дочерним элементом для родительского flexbox элемента и свойством z-index со значением, отличным от auto
  5. Элемент является дочерним элементом для родительского grid элемента и свойством z-index со значением, отличным от auto
  6. Элемент имеет свойство opacity меньше единицы
  7. Элемент имеет свойство mix-blend-mode со значением, отличным от normal
  8. Элемент имеет одно из следующих свойств со значением, отличным от none: transform, filter, perspective, clip-path, mask/ mask-image/ mask-border
  9. Элемент имеет свойство isolation со значением isolate.

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

Обычно достаточно запомнить первые три сценария и чуть-чуть помнить про следующие два. Если браузер рисует что-то, чего вы не ожидали, можно всегда вернуться и подсмотреть остальные.

Для наглядности сверстаем два элемента, один из которых будет содержать в себе еще три дочерних элемента.
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Пример контекстного наложения</title>
  </head>
  <body>
    <div class="boxes">
      <div class="box yellow_box"> <!-- жёлтый элемент -->
        <div class="box_in pink_box"></div> <!-- розовый элемент -->
        <div class="box_in dark_blue_box"></div> <!-- темно синий элемент -->
        <div class="box_in violet_box"></div> <!-- фиолетовый элемент -->
      </div>
      <div class="box orange_box"></div> <!-- тёмный элемент -->
    </div>
  </body>
</html>
.boxes {
  padding: 30px;
  display: inline-block;
}
.box {
  position: relative;
  z-index: 1;
  width: 344px;
  height: 344px;
  padding: 30px;
  border-radius: 15px;
  border: 2px dashed #111;
}

.yellow_box {
  background: #fbd304;
}

.orange_box {
  margin-left: 177px;
  margin-top: -177px;
  background: #d8410b;
}

.box_in {
  width: 200px;
  height: 200px;
  border-radius: 15px;
}
.pink_box {
  border: 2px dashed #111;
  background: #fa7ec1;
}

.dark_blue_box {
  margin-top: -160px;
  margin-left: 40px;
  border: 2px dashed #111;
  background: #045585;
}

.violet_box {
  position: relative;
  z-index: 9999999;
  margin-top: -160px;
  margin-left: 80px;
  background: #118ab2;
  border: 2px dashed #111;
  background: #7c0474;
}
Пока все элементы не позиционированы (по-умолчанию, у всех элементов position: static;), и у них не сформированы контексты наложения - каждый следующий элемент накладывается на предыдущий, то есть отображается ближе к пользователю.
Пусть оба блока (желтый и оранжевый) будут относительно спозиционированы и с z-index: 1, чтобы создать внутри каждого свой контекст наложения:
.box {
  position: relative;
  z-index: 1;
  width: 344px;
  height: 344px;
  padding: 30px;
  border-radius: 15px;
  border: 2px dashed #111;
}
А теперь попробуем сделать так, чтобы фиолетовый блок был поверх оранжевого:
.violet_box {
  position: relative;
  z-index: 9999999;
  margin-top: -160px;
  margin-left: 80px;
  background: #118ab2;
  border: 2px dashed #111;
  background: #7c0474;
}
Почему оранжевый элемент всё ещё перекрывает фиолетовый, ведь у фиолетового элемента значение свойства z-index значительно больше?

Тут сработал контекст наложения и закрытые коробки.

Так как у жёлтого родительского элемента сформирован контекст наложения (жёлтая коробка закрыта), то его дочерние элементы (розовый, темно-синий и фиолетовый) не могут выйти за пределы родительского значения z-index: 1. Все значения z-index для дочерних элементов теперь будут применяться только в пределах жёлтого родительского элемента, a для оранжевого элемента они не будут превышать значения родительского z-index: 1.


Так как же всё-таки разместить фиолетовый элемент ближе остальных?
В данном случае, нужно избавиться от контекста наложения жёлтого родительского элемента.
Есть два варианта как это сделать:
1 вариант - назначить ему position: static; - контекста наложения больше не будет и z-index перестанет работать
2 вариант - убрать свойство z-index: 1; (или назначить z-index: auto;), но оставить position: relative;, если жёлтый элемент должен оставаться позиционированным, что встречается гораздо чаще.

Выбираем второй вариант:
.box {
  position: relative;
  z-index: auto; /* Поставили значение auto*/
  width: 344px;
  height: 344px;
  padding: 30px;
  border-radius: 15px;
  border: 2px dashed #111;
}

.violet_box {
  position: relative;
  z-index: 9999999;
  margin-top: -160px;
  margin-left: 80px;
  background: #118ab2;
  border: 2px dashed #111;
  background: #7c0474;
}
Порядок наложения
Внутри каждого контекста наложения существует свой порядок отрисовки элементов и их компонентов. Ниже перечисление идёт от самого нижнего слоя, до самого верхнего:

  1. Фон (background) и рамки элемента (border);
  2. Позиционированные элементы (включая потомков), у которых значение свойства z-index меньше 0;
  3. Элементы без контекста наложения с display: block;
  4. Элементы со свойством float;
  5. Элементы с display: inline;
  6. Элементы (включая потомков) с z-index: auto или z-index: 0, а также элементы с opacity меньше 1;
  7. Элементы (включая потомков) с z-index больше 0.
Согласно этому порядку, элемент с отрицательным значением z-index никогда не будет ниже фона или рамки родительского элемента.

Контекст наложения — набор правил, на основании которых браузер решает, какой элемент на странице будет выше или ниже других. Условно, если представлять элементы как колоду карт, то правила формирования контекста наложения тасуют колоду. Это одна из основных концепций CSS.
Полезные ссылки
Подробнее про контекст наложения от w3c (для тех кто не знает английский, включите перевод страницы) - https://www.w3.org/TR/CSS21/zindex.html

Статья от хабр про z-index - https://habr.com/ru/post/166435/


Практика
1. Пирамида
Повтори страницу по образцу, сделав так, чтобы зеленые блоки располагались по центру своего родителя.
    2. Много рамок
    Повтори страницу по образцу.
      3. Меню - от простого к сложному
      Простейший способ оформить пункты меню — добавить между ними отступы и задать стили ссылок.
      Для упрощения, у тебя есть часть готового кода, его нужно дополнить:
      1. Задай элементам списка внешний отступ снизу 8px
      2. Задай ссылкам цвет #0088cc

      Подсказка: используй контекстные селекторы
        <!DOCTYPE html>
        <html lang="ru">
          <head>
            <meta charset="utf-8">
            <title>Оформляем пункты, простой вариант</title>
          </head>
          <body>
            <ul class="main-menu">
              <li><a href="#company">О компании</a></li>
              <li><a href="#services">Услуги</a></li>
              <li><a href="#team">Сотрудники</a></li>
              <li><a href="#contacts">Контакты</a></li>
            </ul>
          </body>
        </html>
        
        body {
          padding: 10px;
          font-size: 14px;
          line-height: 1.4;
          font-family: "Arial", sans-serif;
        }
        
        .main-menu {
          width: 150px;
          margin: 0; /убираем верхнее и нижнее поле, равное 1em/
          padding: 10px 15px;
          list-style: none; /убираем маркеры списка/
          background-color: #f5f5f5;
          border: 1px solid #e5e5e5;
        }
        3.1. Меню - от простого к сложному
        Простое, но аккуратное вертикальное меню готово.
        Теперь немного усложним его:
        1. Обнули все отступы у списка и элементов списка
        2. Увеличь ширину списка до 180px
        3. Сделай ссылки меню блочными элементами.
        4. Добавь ссылкам внутренние отступы, вертикальные - 8px и горизонтальные - 14p

        После этого добавим разделители, чтобы визуально улучшить меню
        1. Убери фон и рамки у списка.
        2. Добавь ссылкам сплошную рамку шириной 1px цвета #e5e5e5
        3. Добавь ссылкам отрицательный внешний отступ снизу -1px. Нужен для того, чтобы не возникало двойных рамок на стыке ссылок.
        4. Убери подчеркивание у ссылок.
          text-decoration: none; /*убираем подчеркивание текста ссылок*/
          3.2. Меню - от простого к сложному
          Добавим стили для состояний. Будем считать, что мы находимся на странице Услуги.
          1. Добавь класс active ко второму элементу списка.
          2. Переопредели для ссылок внутри элемента с классом active цвет на white и цвет фона на #0088cc
          3. Задай цвет фона #f5f5f5 при наведении на ссылку
          В итоге мы получим вертикальное меню.

          Подсказка: псевдокласс :hover.
            4. Горизонтальное меню
            Пробуем делать горизонтальное меню сайта.
            Усложним задачу, используй списки и особый тег для навигации по сайту - nav.

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

            Не забудь к стилям списка добавить:
              list-style: none; /*убираем маркеры списка*/
              margin: 0px; /*убираем верхнее и нижнее поле, равное 1em*/
              padding: 0px; /*убираем левый отступ, равный 40px*/
              И для ссылки:
                text-decoration: none; /*убираем подчеркивание текста ссылок*/
                Если возникнут вопросы - обратись к наставнику.
                  4. Меню и основной контент
                  К меню, которое получилось в предыдущем задании добавьте основной контент.
                  Вспоминаем семантику сайта, в качестве подсказки используй списки и особый тег для навигации по сайту.
                    Следующее занятие