Вы когда-нибудь сталкивались с дилеммой позиционирования CSS, когда элемент с position: absolute
позиционируется не так, как вы ожидали? Установка абсолютного позиционирования для элемента позиционирует его относительно его ближайшего предка, для которого задано относительное положение.
На этом изображении элемент с абсолютным позиционированием в обоих случаях позиционируется с помощью одного и того же CSS:
.absolute {
position: absolute;
top: 100%;
left: 0;
}
Однако, при этом он оказывается в разных местах. Это связано с тем, что в первом примере его родительский элемент (розовый элемент) имеет position: relative
, а для второго предок с относительным позиционированием другой (серый элемент).
Стоит отметить, в случае, когда относительное позиционирование отсутствует у всех предков, элемент с position: absolute
будет располагаться относительно <body>
.
В простых случаях, подобных этому, быстрый взгляд на CSS позволяет легко определить, какой предок имеет относительное позиционирование и, если стили не дают желаемого эффекта, можно быстро поправить их соответствующим образом. Но иногда в более сложных кодовых базах (особенно с большим количеством вложенных элементов) определение того, у какого предка элемента относительное позиционирование, может быть сложнее.
Исследование всего кода может занять много времени, но есть простой способ найти ближайшего расположенного родителя в Javascript, который можно применить прямо в консоли браузера.
Если открыть вкладку «Консоль» в инструментах разработчика В Chrome и Firefox, ссылку на текущий выбранный элемент можно получить, набрав $0
. Затем, чтобы найти ближайшего предка этого элемента, у которого значение position
установлено не по умолчанию (static
), можно использовать свойство объекта offsetParent
. Попробуйте выбрать элемент и набрать в консоли:
$0.offsetParent
На самом деле это ещё не сообщает ничего о позиционировании элемента. Чтобы узнать значение свойства position
элемента, можно использовать метод getComputedStyle()
:
getComputedStyle($0.offsetParent).position
Набрав в консоли $_
, можно получить последнее вычисленное выражение, как переменную, так выражение:
$0.offsetParent
показывает элемент. Затем:
getComputedStyle($_).position
возвращает значение свойства position
. Если позиционирование этого элемента отличается от relative
, можно сделать то же самое снова и продолжать движение вверх по дереву DOM, пока не найдется предок, относительно которого позиционируется выбранный элемент. Еще можно написать рекурсивную функцию и перебирать элементы, пока не найдется элемент с нужным позиционированием. Есть несколько предостережений: offsetParent
вернет null
, если для элемента установлено position: fixed
, либо у него или его родителя display: none
.
Finding an Element’s Nearest Relative Positioned Ancestor.
P.S.: В оригинале автор не осилил написать рекурсию для поиска первого из предков с position: relative
. Она может выглядеть как-то так:
let el = $0.offsetParent
while (el && getComputedStyle(el).position !== 'relative') {
el = el.offsetParent
}