Z-index управление

Floating UI — это библиотека для позиционирования всплывающих элементов, таких как тултипы, модальные окна, поповеры и меню. Одним из ключевых аспектов корректного отображения таких элементов является управление слоями отображения (stacking context) через z-index. Floating UI предоставляет гибкие инструменты для контроля этих слоев, позволяя избежать перекрытия и конфликтов с другими элементами интерфейса.


Контекст наложения и Z-index

Каждый элемент на странице находится в определённом контексте наложения (stacking context). Контекст определяется несколькими факторами, включая:

  • Значения CSS-свойств position (relative, absolute, fixed, sticky).
  • Свойства z-index, opacity, transform, filter, perspective.
  • Родительские элементы с явным z-index создают новый контекст для вложенных элементов.

В Floating UI контроль Z-index критичен, так как всплывающие элементы должны появляться над контентом страницы, но под нужными слоями, например под модальным фоном или поверх меню навигации.


Использование middleware для управления Z-index

Floating UI позволяет модифицировать поведение всплывающих элементов через middleware. Для Z-index применяется несколько подходов:

1. autoUpdate и управление позиционированием

Хотя autoUpdate отвечает за автоматическое пересчитывание позиции, сочетание его с правильным Z-index позволяет поддерживать динамическое наложение при изменении DOM:

import { computePosition, autoUpdate, offset, flip, shift } from '@floating-ui/dom';

const reference = document.querySelector('#button');
const floating = document.querySelector('#tooltip');

autoUpdate(reference, floating, () => {
  computePosition(reference, floating, {
    middleware: [offset(8), flip(), shift({ padding: 5 })],
  }).then(({ x, y }) => {
    Object.assign(floating.style, {
      left: `${x}px`,
      top: `${y}px`,
      zIndex: 1000
    });
  });
});
  • Здесь zIndex: 1000 задаёт слой над большинством элементов страницы.
  • Middleware flip и shift корректируют позицию при выходе за границы окна.

2. Управление через strategy и positioning

Floating UI поддерживает два режима позиционирования:

  • absolute — относительно ближайшего позиционированного родителя.
  • fixed — относительно окна просмотра, не подчиняется scroll-контексту.

Для элементов с высокой видимостью (modals, popovers) рекомендуется fixed вместе с высоким z-index:

computePosition(reference, floating, {
  strategy: 'fixed',
}).then(({ x, y }) => {
  Object.assign(floating.style, {
    position: 'fixed',
    left: `${x}px`,
    top: `${y}px`,
    zIndex: 2000
  });
});

Динамический Z-index через Floating UI

Для сложных интерфейсов часто требуется динамическое вычисление Z-index, чтобы всплывающий элемент не перекрывал другие интерактивные компоненты. Floating UI позволяет использовать middleware для этого:

import { offset, autoUpdate, shift } from '@floating-ui/dom';

function setDynamicZIndex(floating) {
  const elements = document.querySelectorAll('*');
  let maxZ = 0;

  elements.forEach(el => {
    const z = parseInt(window.getComputedStyle(el).zIndex, 10);
    if (!isNaN(z)) maxZ = Math.max(maxZ, z);
  });

  floating.style.zIndex = maxZ + 1;
}

autoUpdate(reference, floating, () => {
  setDynamicZIndex(floating);
});
  • Скрипт находит текущий максимальный Z-index на странице и ставит всплывающий элемент поверх него.
  • Подходит для модальных окон, диалогов и меню, создаваемых динамически.

Управление Z-index для nested floating elements

Когда всплывающие элементы вложены друг в друга (например, меню с подменю), Z-index должен сохранять иерархию:

const parentMenu = document.querySelector('#menu');
const childMenu = document.querySelector('#submenu');

computePosition(parentMenu, childMenu, {
  middleware: [offset({ mainAxis: 0, crossAxis: 10 }), flip()],
}).then(({ x, y }) => {
  Object.assign(childMenu.style, {
    left: `${x}px`,
    top: `${y}px`,
    zIndex: parseInt(parentMenu.style.zIndex, 10) + 1
  });
});
  • Подменю получает z-index, на единицу выше родительского меню.
  • Поддерживается правильная визуальная иерархия без конфликтов.

Использование CSS-переменных для контроля слоев

Для удобного управления слоями можно использовать CSS-переменные в сочетании с Floating UI:

:root {
  --z-tooltip: 1000;
  --z-popover: 2000;
  --z-modal: 3000;
}

.tooltip {
  z-index: var(--z-tooltip);
}

.popover {
  z-index: var(--z-popover);
}

.modal {
  z-index: var(--z-modal);
}
  • Позволяет централизованно управлять всеми Z-index.
  • Легко комбинируется с middleware Floating UI, присваивая элементу нужную переменную при рендере.

Практические рекомендации

  • Для всплывающих элементов, которые должны быть всегда видимыми, использовать strategy: fixed и Z-index выше основного контента.
  • Для вложенных элементов поддерживать иерархический Z-index через добавление единицы к родительскому слою.
  • При динамическом добавлении элементов вычислять максимальный Z-index на странице и ставить новый элемент поверх.
  • Комбинировать Floating UI middleware (flip, shift, offset) с управлением Z-index для корректного поведения при изменении DOM и размеров окна.

Эти подходы позволяют Floating UI работать корректно в сложных интерфейсах, где всплывающие элементы должны точно соблюдать слои отображения без перекрытия критически важных компонентов.