Урок 05

Display, position, z-index

Что такое display

display — как элемент участвует в потоке документа.

Основные значения:

  • block — блочный.
  • inline — строчный.
  • inline-block — строчный, но с блоковыми свойствами.
  • none — удалить из потока.
  • flex — flex-контейнер.
  • grid — grid-контейнер.
  • inline-flex, inline-grid — то же, но строчные.

block

Поведение:

  • Занимает всю ширину родителя.
  • Начинается с новой строки.
  • Может иметь width, height, margin, padding.

Примеры тегов: div, p, h1–h6, ul, li, section.

.box {
    display: block;
    width: 300px;
}

inline

Поведение:

  • Занимает только по содержимому.
  • Не переносится на новую строку.
  • Нельзя задать width, height.
  • Вертикальные margin и padding не работают (горизонтальные — да).

Примеры: span, a, strong, em, code.

.link {
    display: inline;
}

inline-block

Гибрид:

  • Внешне как inline — не переносится.
  • Внутри как block — можно размеры, margin, padding.
.badge {
    display: inline-block;
    padding: 4px 10px;
    background: #c1442e;
    color: #fff;
    border-radius: 999px;
}

Когда: маленькие элементы с padding, метки, кнопки-ссылки.

none

.hidden {
    display: none;
}

Что даёт: элемент полностью удалён из потока. Не занимает места.

Отличие от visibility: hidden:

  • display: none — не занимает места.
  • visibility: hidden — занимает, но невидим.

Правило:

  • display: none — для скрытия (модалки, дефолтные состояния).
  • visibility: hidden — чтобы сохранить layout.

Адаптив через display

.desktop-only { display: block; }
.mobile-only { display: none; }

@media (max-width: 768px) {
    .desktop-only { display: none; }
    .mobile-only { display: block; }
}

Правило: не использовать @media для скрытия там, где можно flex-wrap.

position

5 значений:

  • static — по умолчанию.
  • relative — относительно своего места.
  • absolute — относительно ближайшего позиционированного предка.
  • fixed — относительно viewport.
  • sticky — гибрид relative и fixed.

static

По умолчанию.

  • Не реагирует на top / right / bottom / left.
  • Не реагирует на z-index.

relative

.box {
    position: relative;
    top: 10px;
    left: 20px;
}

Что даёт:

  • Сдвиг относительно своего исходного места.
  • Место в потоке сохраняется.
  • z-index работает.
  • Цель для absolute-детей.

Правило: relative — чаще всего для создания «точки отсчёта» для absolute.

absolute

.parent {
    position: relative;
}

.child {
    position: absolute;
    top: 0;
    right: 0;
}

Что даёт:

  • Позиционируется относительно ближайшего позиционированного предка (relative, absolute, fixed, sticky).
  • Удалён из потока — не занимает места.
  • Размер — по содержимому, если не задан.

Центрирование:

.center {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

Когда: бейджи, тултипы, модалки, наложения.

fixed

.header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 100;
}

Что даёт:

  • Позиционируется относительно viewport (окна браузера).
  • Не двигается при скролле.
  • Удалён из потока.

Когда: фиксированные шапки, кнопки «наверх», cookie-баннеры.

Правило: помнить про мобильные (может мешать).

sticky

.sticky-header {
    position: sticky;
    top: 0;
    z-index: 10;
}

Что даёт:

  • Ведёт себя как relative, пока не дойдёт до top.
  • Потом «прилипает».

Работает если:

  • У родителя есть высота больше элемента.
  • Нет overflow: hidden у предков.
  • Задан top / bottom / left / right.

Когда: sticky-шапки, оглавления, sticky-сайдбары.

Правило: sticky не работает, если между ним и скроллом есть overflow: hidden.

z-index

.modal {
    position: fixed;
    z-index: 1000;
}

Что делает: порядок наложения. Больше — выше.

Работает только если:

  • position — не static (relative / absolute / fixed / sticky).
  • Или display: flex / grid с элементом (для direct children).

Шкала:

--z-base: 1;
--z-dropdown: 100;
--z-sticky: 200;
--z-modal: 500;
--z-notification: 1000;
--z-tooltip: 2000;

Правило: договориться о шкале в проекте и не использовать 9999.

Stacking context

Проблема: z-index: 9999 не помогает.

Причина: элемент в другом stacking context — своём «слое», где z-index изолирован.

Создают новый stacking context:

  • position + z-index (не auto).
  • opacity < 1.
  • transform, filter, perspective, will-change.
  • isolation: isolate.
  • mix-blend-mode != normal.
  • position: fixed или sticky.

Правило: если z-index не работает — ищи предка со stacking context.

overflow

overflow: visible;   /* по умолчанию */
overflow: hidden;    /* обрезать */
overflow: auto;      /* скролл, если нужно */
overflow: scroll;    /* всегда скроллбар */

/* Отдельно по осям */
overflow-x: auto;
overflow-y: hidden;

Что важно: overflow: hidden создаёт BFC (Block Formatting Context) и обрезает margin. Также может ломать sticky.

Правило: overflow-x: auto для горизонтального скролла таблиц, кода.

Пример: sticky header

.header {
    position: sticky;
    top: 0;
    z-index: 100;
    background: #fff;
    border-bottom: 1px solid #e5e5e5;
}

body {
    padding-top: 0;   /* без offset */
}

Пример: dropdown

.dropdown {
    position: relative;
}

.dropdown__menu {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 200px;
    background: #fff;
    border: 1px solid #e5e5e5;
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.1);
    z-index: 10;
}

Практика

1. Sticky header на странице с длинным контентом.

2. Бейдж в углу карточки (relative + absolute).

3. Модальное окно (fixed + z-index).

4. Dropdown по клику (через :focus-within или JS).

5. Скролл таблицы через overflow-x: auto.

Частые ошибки

1. absolute без relative родителя:

Улетает к body

Решение: position: relative у родителя.

2. z-index без position:

z-index: 999;   /* не работает */

Решение: position: relative или другое.

3. z-index: 9999 без понимания:

Не работает — stacking context

Решение: найти контекст.

4. overflow: hidden у родителя sticky:

Sticky не работает

Решение: убрать overflow: hidden.

5. display: none вместо visibility:

Layout прыгает

Решение: visibility: hidden для сохранения места.

6. inline + width:

span { width: 100px; }   /* не работает */

Решение: inline-block или block.

7. Fixed header и якоря:

Якорь прокручивает под header

Решение: scroll-margin-top на цели:

section { scroll-margin-top: 80px; }

8. Модалка без блокировки скролла body:

Body скроллится под модалкой

Решение: при открытии — body { overflow: hidden; }.

Итог

  • display: block, inline, inline-block, none.
  • position: static, relative, absolute, fixed, sticky.
  • z-index — только с position.
  • Stacking context — почему не работает z-index.
  • overflow — обрезка и скролл.
  • Sticky — не работает с overflow hidden.
  • Absolute — от ближайшего позиционированного.
  • Fixed — от viewport.
  • scroll-margin-top — для якорей.

Дальше — Flexbox: контейнер, элементы, выравнивание.