Floating UI — это библиотека для позиционирования всплывающих
элементов, таких как тултипы, модальные окна, поповеры и меню. Одним из
ключевых аспектов корректного отображения таких элементов является
управление слоями отображения (stacking context) через
z-index. Floating UI предоставляет гибкие инструменты для
контроля этих слоев, позволяя избежать перекрытия и конфликтов с другими
элементами интерфейса.
Каждый элемент на странице находится в определённом контексте наложения (stacking context). Контекст определяется несколькими факторами, включая:
position (relative,
absolute, fixed, sticky).z-index, opacity,
transform, filter,
perspective.z-index создают новый
контекст для вложенных элементов.В Floating UI контроль Z-index критичен, так как всплывающие элементы должны появляться над контентом страницы, но под нужными слоями, например под модальным фоном или поверх меню навигации.
middleware для управления Z-indexFloating UI позволяет модифицировать поведение всплывающих элементов через middleware. Для Z-index применяется несколько подходов:
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 задаёт слой над большинством
элементов страницы.flip и shift корректируют
позицию при выходе за границы окна.strategy и positioningFloating 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 позволяет использовать 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 должен сохранять иерархию:
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-переменные в сочетании с 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);
}
strategy: fixed и Z-index выше основного
контента.flip,
shift, offset) с управлением Z-index для
корректного поведения при изменении DOM и размеров окна.Эти подходы позволяют Floating UI работать корректно в сложных интерфейсах, где всплывающие элементы должны точно соблюдать слои отображения без перекрытия критически важных компонентов.