Координаты
Когда нужно расположить объект в произвольном месте на странице, нужно не перепутать верх и низ.
Обновлено 12 сентября 2022
Кратко
Чтобы перемещать и позиционировать элементы на экране в браузере имеется система координат. Оси координат начинаются в левом верхнем углу экрана и идут вправо для оси x и вниз для оси y.
Позиционирование с помощью координат может быть относительно окна браузера или относительно отдельного элемента. Всего существует две системы координат: одна начинается от угла HTML-страницы (документа), а вторая от угла окна браузера. С помощью первой можно определять как элемент расположен относительно всей страницы, а с помощью второй – как элемент расположен относительно окна браузера и того что там находится. Объекты события мыши и тач-события содержат координаты места на экране и в документе, где событие произошло: page X / page Y – для документа, client X / client Y – для экрана.
Координатами элемента является расстояние в пикселях от осей системы координат до его левого верхнего угла. С помощью метода элемента get Bounding Client Rect ( ) можно получить подробные данные о координатах элемента и его размере.
Как пишется
document.addEventListener('click', event => console.log('Позиция x относительно документа', event.pageX) console.log('Позиция y относительно документа', event.pageY) console.log('Позиция x относительно экрана', event.clientX) console.log('Позиция y относительно экрана', event.clientY)>, false) // const rect = element.getBoundingClientRect()
document.addEventListener('click', event => console.log('Позиция x относительно документа', event.pageX) console.log('Позиция y относительно документа', event.pageY) console.log('Позиция x относительно экрана', event.clientX) console.log('Позиция y относительно экрана', event.clientY) >, false) // const rect = element.getBoundingClientRect()
Как понять
Система координат в браузере аналогична плоской системе координат из школьной алгебры. Есть две оси: ось y и ось x, на этой плоскости располагаются все элементы сайта. Единственным отличием от классической системы координат является то, что положительное направление оси y в браузере повёрнуто вниз. Это значит, что элементы с положительным значением по оси y будут находиться внизу относительно оси x, а с отрицательным – наверху.
Позиция элемента задаётся числом пикселей от начала системы координат по соответствующей оси.
Начало системы координат можно отсчитывать относительно окна браузера, либо относительно всего документа. Когда страница не прокручена, то начала этих осей совпадают в левом верхнем углу окна. Если прокручивать страницу вниз, то соответственно начало координат документа останется таким же, а начало оси координат окна будет смещаться. Такое разделение может быть полезно для разных задач, например можно анимировать элементы, только когда они попадают на экран, считая координаты относительно документа. А можно давать перетаскивать какой-либо элемент, но только в пределах окна браузера.
На рисунках page X и page Y – оси системы координат относительно документа, а client X и client Y – оси системы координат относительно окна браузера. Соответственно page X Offset и page Y Offset – это смещение относительно всего документа, а client X Offset и client Y Offset – относительно окна. На практике используются очень похожие названия, потому для текущих примеров будем использовать их.
Ниже схема осей координат, когда страница не прокручена. В таком состоянии оси совпадают, и координаты элементов относительно окна и относительно документа будут совпадать.
Но если прокрутить страницу (например вниз), но ситуация изменится. Начало документа уйдёт наверх, а значит и начало осей координат. Оси координат окна теперь будут начинаться там, где мы остановим прокрутку.
💡 Стоит обратить внимание на то, что координаты – это расстояние от осей до его верхнего левого угла. Потому стрелки на схеме начинаются от угла элемента с текстом Button.
Смещение относительно окна браузера
В объекте события мыши из полей client X / client Y можно узнать в каком месте относительно системы координат окна произошло событие, например клик.
Если нужно узнать как элемент расположен относительно окна, то в этом поможет метод get Bounding Client Rect ( ) . Вызов этого метода возвращает объект с полями x , y , top , left , right , bottom , width и height , то есть полная информация о геометрии элемента. В полях x и y содержатся координаты элемента.
💡 Позиционирование относительно окна гораздо проще понять, если посмотреть, как располагается элемент с position : fixed . Элемент с этим свойством будет находиться в окне в одних и те же координатах, вне зависимости от того насколько прокручен документ.
Смещение относительно документа
Если нужно получить данные, в каком месте документа произошло событие, то это можно узнать из полей page X / page Y в объекте события.
Информацию о том, как элемент расположен относительно документа нельзя узнать из какого-то свойства или метода, её необходимо вычислять самостоятельно. Самым простым способом это можно сделать сложив координаты относительно окна из метода get Bounding Client Rect ( ) со смещением самого окна относительно документа. Смещение окна браузера можно узнать из полей window . page X Offset и window . page Y Offset – это число пикселей на которое прокручен документ по горизонтали и вертикали.
const rect = element.getBoundingClientRect() console.log('Смещение X относительно документа:', rect.x + pageXOffset)console.log('Смещение Y относительно документа:', rect.y + pageYOffset)
const rect = element.getBoundingClientRect() console.log('Смещение X относительно документа:', rect.x + pageXOffset) console.log('Смещение Y относительно документа:', rect.y + pageYOffset)
💡 Позиционирование относительно документа так же можно понять, если посмотреть как располагается элемент с position : absolute . При прокрутке окна этот элемент будет смещаться вместе с ним.
Наглядно как работают оси, и как располагаются элементы можно посмотреть в демо. В начальном состоянии положения осей и элементов, которые расположены относительно них совпадают. Оси относительно экрана сделаны крупнее, чтобы их было видно всегда. Если прокрутить страницу по вертикали или горизонтали будет видно как оси относительно экрана остаются на месте, а оси относительно документа уходят вместе с движением прокрутки.
На практике
Егор Огарков советует
🛠 С помощью значения координат можно узнавать какой элемент находится в окне по этим координатам. Метод document . element From Point ( ) возвращает элемент по переданным ему координатам.
const x = 100const y = 200 const foundElement = document.elementFromPoint(x, y)
const x = 100 const y = 200 const foundElement = document.elementFromPoint(x, y)
Метод вернёт самый глубоко вложенный элемент в DOM-дереве по этим координатам, который может оказаться не тем, что вам нужен.
🛠 Координаты чаще всего используются для создания поведения перетаскивания элементов по экрану. Используя client X / client Y или page X / page Y из события можно менять координаты самого элемента.
Как вычислить координаты html элемента
Как вычислить (получить) позицию html елемента. offsetTop и offsetLeft даёт относительное значение (не всегда отчёт от точки [x=0,y=0] начала координат). Гугл даёт «недоделанный» вариант http://javascript.ru/ui/offset. Не «как динамический во время scroll определить текущее местоположение элемента по отношению к родителю«, а как получить абсолютные координаты относительно левого верхнего угла содержимого страницы. Второй вопрос «определить текущее местоположение элемента по отношению к родителю» ещё раз повторяю, абсолютные координаты относительно левого верхнего угла содержимого страницы. Нужно для «подвешивания» элементов к текущей верстке (что бы вывести на/возле определённого элемента подсказку, сообщение, рекламу и т.п.) например так:
document.getElementById("act_holder").style.position= "absolute"; document.getElementById("act_holder").style.display = "block"; document.getElementById("act_holder").style.top = (getOffset(document.getElementById("act_hlp")).top - 75 ) + "px"; document.getElementById("act_holder").innerHTML = "элемент занят";
3 ответа 3
Вот код с javascript.ru собраный до кучи.
function getOffset(elem) < if (elem.getBoundingClientRect) < var box = elem.getBoundingClientRect(); var body = document.body; var docElem = document.documentElement; var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop; var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft; var clientTop = docElem.clientTop || body.clientTop || 0; var clientLeft = docElem.clientLeft || body.clientLeft || 0; return < top: Math.round(box.top + scrollTop - clientTop), left: Math.round(box.left + scrollLeft - clientLeft) >> else < var top=0, left=0 while(elem) < top = top + parseFloat(elem.offsetTop); left = left + parseFloat(elem.offsetLeft); elem = elem.offsetParent ; >return ; > >
Немного комментариев: ф-ция getBoundingClientRect вызвала спор, mozilla цитата
Возвращаемое значение getBoundingClientRect — это объект TextRectangle, содержащий свойства только для чтения left, top, right и bottom, описывающие бокс с границами в пиксельном измерении. Значения top и left даются относительно верхнего левого угла порта просмотра.
т.е. уже с учётом скролла и отступов документа, которые приходится вычитать если нужны координаты относительно начала системы координат листа (левый верхний угол документа). Даная функция getBoundingClientRect даст верный результат, если выполняется два условия: 1) позиция скроллинга ноль (на старте часто так), 2) если у документа (body) отступы не заданы, или заданы в ноль. Так как эти условия не всегда соблюдены — приходится использывать более сложные решения.
От себя добавлю, что если используется система отчёта position=fixed то getBoundingClientRect выдаст координаты которые подойдут к этой системе отчёта, но fixed редко используется, поскольку при изменении позиции скрола — позиция на экране сохраняется и елемент будет «плавать». А для absolute и static прийдётся делать пересчёт коодинат. Система relative — просто относительные координаты, в отдельных случаях её можно использовать.