Получение геометрических размеров элементов в JavaScript

Раздел: Веб-разработка -> Работа с размерами

Различные подходы к измерению размеров элементов

Как получить истинные размеры элемента, изменённые с помощью трансформаций (scale, rotate)?

Метод getBoundingClientRect()

Этот метод возвращает объект DOMRect с актуальными значениями width, height, top, left и другими. В отличие от offsetWidth/offsetHeight, он учитывает любые CSS трансформации, примененные к элементу или его родителям. Результат соответствует видимому размеру элемента на экране.

const element = document.querySelector('.card');
const rect = element.getBoundingClientRect();
console.log('Ширина:', rect.width);
console.log('Высота:', rect.height);

размеры js (получение размеров элементов в js)

Цель использования: позиционирование всплывающих подсказок, контекстных меню, привязка к элементу после анимаций, получение координат для событий мыши.

Типичные проблемы:

  • При скрытом элементе (display: none) возвращает нулевые размеры. Решение - временно показать элемент или использовать другие методы.
  • Полученные значения - дробные числа, что может влиять на точность при сравнении.
  • Метод возвращает размеры относительно viewport, поэтому при прокрутке страницы значения меняются.

Как получить ширину и высоту элемента, включая рамки и полосы прокрутки, но без учёта трансформаций?

Свойства offsetWidth и offsetHeight

Данные свойства возвращают целочисленные значения, включающие padding, border и вертикальную полосу прокрутки (если она отображается). Трансформации (scale, rotate) не изменяют эти значения.

const el = document.getElementById('block');
console.log('offsetWidth:', el.offsetWidth);
console.log('offsetHeight:', el.offsetHeight);

Style border width js (стиль border-width в javascript)

Цель: когда необходимо измерить фактическую занимаемую площадь элемента без влияния масштабирования, например, для макетов с фиксированной сеткой или при расчёте положения элементов в каруселях.

Типичные ошибки:

  • Значения равны нулю, если элемент или его родители имеют свойство display: none. Решение - использовать getBoundingClientRect() или временно изменить visibility.
  • Свойства не учитывают box-sizing: border-box - они всегда возвращают полный размер. Это может вызвать путаницу при сравнении с заданными в CSS шириной и высотой.

Как узнать размер внутренней области элемента, доступной для содержимого?

Свойства clientWidth и clientHeight

Эти свойства возвращают размер видимой области внутри элемента, исключая border, scrollbar, но включая padding. Для элементов с box-sizing: border-box clientWidth соответствует width минус border (и scrollbar, если отображается).

const container = document.querySelector('.scrollable');
console.log('clientWidth:', container.clientWidth);
console.log('clientHeight:', container.clientHeight);

Js width (ширина элемента в javascript)

Цель: вычисление свободного места для дочерних элементов, определение необходимости добавления прокрутки, работа с событиями в пределах содержимого.

Проблемы:

  • При отображении полосы прокрутки clientWidth оказывается меньше, чем offsetWidth. Это может быть неожиданно, если разработчик ожидает одинаковые значения.
  • Для элементов с overflow: hidden scrollbar отсутствует, поэтому clientWidth будет равен offsetWidth минус border.

Как определить полный размер содержимого, включая прокрученные области?

Свойства scrollWidth и scrollHeight

Данные свойства возвращают размер всего содержимого элемента, даже если оно выходит за границы контейнера и требует прокрутки. Включают padding, но не border.

const content = document.querySelector('#long-content');
console.log('scrollWidth:', content.scrollWidth);
console.log('scrollHeight:', content.scrollHeight);

Цель: проверка переполнения контейнера, вычисление максимальной прокрутки, динамическое изменение высоты элемента по содержимому.

Нюансы:

  • Если элемент не прокручивается (overflow: visible), scrollWidth/scrollHeight могут быть меньше, чем clientWidth/clientHeight? На самом деле scrollWidth >= clientWidth. Для непрокручиваемого содержимого они равны.
  • При вертикальной прокрутке scrollWidth обычно равен clientWidth (если горизонтальной прокрутки нет).
  • Для скрытых элементов значения равны 0.

Как получить значение CSS-свойства width или height, заданное в стилях?

Функция getComputedStyle()

Позволяет извлечь вычисленное (или заданное) значение любого CSS-свойства в виде строки с единицами измерения. Для получения числового значения можно использовать parseFloat.

const el = document.querySelector('.box');
const style = window.getComputedStyle(el);
const width = parseFloat(style.width);
const height = parseFloat(style.height);
console.log('Width:', width, 'px');
console.log('Height:', height, 'px');

Цель: когда требуется узнать размер, указанный автором стилей, а не рендеренный (например, для сохранения пропорций при адаптации).

Ограничения:

  • Возвращает строку, поэтому необходима обработка.
  • Для свойства width: auto может вернуть 'auto', что не подходит для вычислений.
  • Не учитывает трансформации и фактические видимые размеры.

Практические демонстрации получения размеров

Пример 1. Влияние CSS трансформации на показания разных методов

Создаётся элемент с фиксированными размерами, затем применяется scale(0.5). Метод getBoundingClientRect корректно отражает уменьшение, а offsetWidth остаётся неизменным.

Пример
const el = document.createElement('div');
el.style.width = '200px';
el.style.height = '100px';
el.style.background = 'steelblue';
document.body.appendChild(el);

console.log('До трансформации:');
console.log('offsetWidth:', el.offsetWidth);
console.log('getBoundingClientRect().width:', el.getBoundingClientRect().width);

el.style.transform = 'scale(0.5)';

console.log('После scale(0.5):');
console.log('offsetWidth:', el.offsetWidth);
console.log('getBoundingClientRect().width:', el.getBoundingClientRect().width);
До трансформации:
offsetWidth: 200
getBoundingClientRect().width: 200
После scale(0.5):
offsetWidth: 200
getBoundingClientRect().width: 100

Ключевой вывод: getBoundingClientRect необходимо использовать, если размеры элемента меняются из-за трансформаций.

Пример 2. Определение переполнения контейнера с помощью scrollHeight

Даны два одинаковых по внешнему виду контейнера. В одном содержимое не превышает высоту, в другом - требует прокрутки. Проверка на переполнение выполняется сравнением scrollHeight и clientHeight.

Пример
// Создание контейнеров
function createContainer(text, overflowContent) {
  const container = document.createElement('div');
  container.style.width = '200px';
  container.style.height = '100px';
  container.style.overflow = overflowContent ? 'auto' : 'hidden';
  container.style.border = '1px solid gray';
  container.style.marginBottom = '10px';
  container.textContent = text;
  if (overflowContent) {
    const inner = document.createElement('div');
    inner.style.height = '150px';
    inner.style.background = 'lightcoral';
    container.appendChild(inner);
  }
  document.body.appendChild(container);
  return container;
}

const normal = createContainer('Нормальный', false);
const overflow = createContainer('С переполнением', true);

console.log('Нормальный контейнер:');
console.log('clientHeight:', normal.clientHeight, 'scrollHeight:', normal.scrollHeight);
console.log('Переполнение:', normal.scrollHeight > normal.clientHeight);

console.log('Контейнер с переполнением:');
console.log('clientHeight:', overflow.clientHeight, 'scrollHeight:', overflow.scrollHeight);
console.log('Переполнение:', overflow.scrollHeight > overflow.clientHeight);
Нормальный контейнер:
clientHeight: 100 scrollHeight: 100
Переполнение: false
Контейнер с переполнением:
clientHeight: 100 scrollHeight: 150
Переполнение: true

Пример 3. Получение числового значения ширины из CSS с помощью getComputedStyle

Элемент имеет ширину, заданную в процентах. Метод offsetWidth возвращает пиксельное значение, а getComputedStyle - строку с исходным значением (например, '50%'). Приведение к числу с parseFloat извлекает только число, отбрасывая единицу.

Пример
const parent = document.createElement('div');
parent.style.width = '400px';
parent.style.background = '#eee';
document.body.appendChild(parent);

const child = document.createElement('div');
child.style.width = '50%';
child.style.height = '50px';
child.style.background = 'orange';
parent.appendChild(child);

const computed = window.getComputedStyle(child);
console.log('getComputedStyle width:', computed.width);           // '50%' или '200px' (в зависимости от рендера)
console.log('Парсинг:', parseFloat(computed.width));             // число, например 200
console.log('offsetWidth:', child.offsetWidth);                  // всегда пиксели, 200
getComputedStyle width: 200px
Парсинг: 200
offsetWidth: 200

Примечание: в стандартной ситуации getComputedStyle возвращает пиксельное значение, если элемент уже отрендерен. Однако для изначально скрытых элементов может вернуть 'auto' или другое.

Получение размеров элементов в JS - comments

En
размеры js (javascript)