Angular IDPStrong Junior
Модулі / Розмітка й стилі / Позиціонування і шари
🔥 0

Модуль 1 · урок 7 з 14

Позиціонування і шари

Позиціонування — це те, чим роблять випадайки, тултіпи, липкі шапки й модалки. Тут же живе найзагадковіший баг фронтенду: «я поставив z-index: 9999, а воно все одно під сусіднім блоком». Розберемо, чому так, — і більше це питання не виникатиме.

П'ять значень position

ЗначенняВідносно чого зсувМісце в потоціДе застосовують
staticЗсуву немає взагаліЗаймаєСтан за замовчуванням
relativeСамого себеЗаймає — місце лишається порожнімДрібний зсув; частіше — як «якір» для absolute
absoluteНайближчого позиціонованого предкаВипадаєБейджі, іконки в полі, випадайки
fixedВікна браузераВипадаєШапка, модалка, кнопка-дія
stickyНайближчого предка зі скроломЗаймаєЛипкі заголовки таблиць і секцій

Головне про absolute: від кого рахується

absolute шукає найближчого предка, у якого position не static, і позиціонується відносно нього. Якщо такого предка немає — відносно всієї сторінки, і елемент відлітає кудись у верхній лівий кут.

.field { position: relative; }          /* якір */
.field__icon {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);          /* точне вертикальне центрування */
}

Тому правило звучить так: ставиш дитині absolute — постав батькові relative. Це та сама пара, яка робить іконку в полі, бейдж на аватарі й кнопку закриття в кутку картки.

Дрібниця, яка ламає тултіпи

transform, filter і will-change у предка теж роблять його «якорем» для fixed-нащадків. Тобто модалка з position: fixed усередині блока з transform: translateX(...) раптом позиціонується не відносно вікна, а відносно цього блока. Виглядає як містика, поки не знаєш.

Sticky і чому він мовчки не працює

.table__head {
  position: sticky;
  top: 0;             /* обов'язково: без зміщення sticky нічого не робить */
  background: var(--surface);   /* інакше вміст просвічуватиме крізь */
  z-index: 1;
}

Три умови, без яких sticky просто поводиться як static:

  1. Задано хоча б одне зміщення: top, bottom, left або right.
  2. У жодного предка немає overflow: hidden чи auto — інакше «липкість» прив'язується до цього предка й ефект зникає.
  3. Батько вищий за сам елемент — інакше липнути нема куди.

Контекст накладання: чому z-index не слухається

z-index порівнюється лише між сусідами в межах одного контексту накладання. Якщо два елементи в різних контекстах, їхні числа взагалі не порівнюються — виграє той, чий контекст вище.

КОРІНЬ СТОРІНКИ .card--a z-index: 1 · opacity: .99 СВІЙ КОНТЕКСТ НАКЛАДАННЯ .tooltip · z-index: 9999 .card--b z-index: 2 Перемагає ця картка цілком — разом з усім своїм вмістом. 9999 усередині сусіда не рахується. Порівнюються 1 і 2 — контексти карток. Число 9999 живе всередині картки A і назовні не виходить.
Числа z-index порівнюються лише всередині одного контексту. Саме тому «підняти» тултіп у сусідньому контексті числом неможливо.

Що створює новий контекст накладання

  • position не static разом із будь-яким z-index, крім auto.
  • opacity менша за 1 — так, навіть 0.99.
  • transform, filter, backdrop-filter, perspective.
  • will-change на будь-якій із цих властивостей.
  • isolation: isolate — єдиний, який роблять навмисно саме заради цього.
  • Елементи всередині flex або grid із заданим z-index.

Як з цим жити на практиці

Робочі правила
  • Завести шкалу шарів у токенах: --z-dropdown: 100, --z-modal: 400.
  • Значення тільки з цієї шкали, ніяких випадкових чисел.
  • Модалки й тултіпи рендерити в кінець <body> — в Angular це робить CDK Overlay.
  • isolation: isolate на картці, щоб її внутрішні шари не лізли назовні.
Симптоми проблеми
  • z-index: 9999 будь-де в коді.
  • Випадайка обрізається краєм картки — це overflow: hidden у предка.
  • Модалка з'явилась усередині панелі, а не поверх сторінки.
  • Липка шапка перестала липнути після додавання скролу в контейнер.
Навіщо це в модулі про верстку

У модулі 6 ти робитимеш модальні форми, а в модулі 5 — таблицю з липкою шапкою. Обидві ці штуки ламаються рівно на тому, що описано вище. Angular Material вирішує це за тебе через CDK Overlay, але коли щось піде не так, шукати причину доведеться саме тут.