Позиционирование и слои
Вопрос
Относительно чего считается absolute, и почему z-index иногда не поднимает элемент над соседом?
Короткий ответ
static — обычный поток. relative оставляет место в потоке и сдвигает сам бокс. absolute вынимает из потока и считается относительно ближайшего предка, который не static. Если такого нет, относительно начального содержащего блока. fixed привязан к вьюпорту, пока предок не создаёт содержащий блок трансформом, фильтром, contain или will-change. sticky держится в своём скролл-контейнере в заданном диапазоне.
z-index сравнивается только внутри одного контекста наложения. Новый контекст создают, среди прочего, position не static вместе с z-index не auto, opacity меньше 1, transform, filter, isolation: isolate. Элемент с z-index: 9999 внутри такого контекста не перепрыгнет соседний контекст родителя с меньшим уровнем.
Разбор
Модалка, которую «не перекрыть», часто сидит внутри карточки с transform или opacity. Её выносят порталом ближе к body либо поднимают весь контекст предка. Во Vue 3 для этого есть Teleport.
overflow: hidden вместе с позиционированием тоже участвует в создании контекста в современных браузерах, если задан не visible. Отсюда классический баг: выпадашка обрезается и одновременно проигрывает по слоям.
Отдельный слой композитинга (transform, opacity, will-change) браузер может двигать на GPU, не перерисовывая соседей. Бесконечный will-change: transform на всём списке память не экономит.
На что смотрят на senior
Анимация transform и opacity остаётся на композиторе. Анимация top, left, width и height гоняет layout. На собеседовании достаточно назвать это и предложить измерить в Performance, а не объявлять любой transition дешёвым.
content-visibility: auto пропускает раскладку далёких блоков списка. Это уместно после того, как список уже корректно рендерится, и с пониманием, что скринридер и поиск по странице зависят от того, что реально в DOM.
Типичные ошибки
- Ставить огромный
z-indexи не смотреть предков. - Ждать, что
fixedвсегда относительно окна, когда у предка естьtransform. - Анимировать геометрию там, где хватает сдвига и прозрачности.
Задача
У модалки z-index: 9999, она всё равно под шапкой. У предка модалки стоит transform: translateZ(0), у шапки z-index: 10. Почему большой индекс не помогает?
Показать ответ
transform создаёт контекст наложения. z-index модалки сравнивается только внутри этого контекста, а не со всей страницей.
Наружу торчит весь контекст предка. Если у предка нет своего z-index выше шапки, шапка с 10 окажется выше всего поддерева, каким бы большим ни был индекс внутри.