DOM Advanced

Размеры элементов и прокрутка

Различать clientWidth/Height, offsetWidth/Height, scrollWidth/Height, и использовать getBoundingClientRect для позиционирования относительно viewport.

Продвинутый (Advanced)

Кратко

Размеры элементов: clientWidth/Height (контент + padding), offsetWidth/Height (контент + padding + border + scrollbar), scrollWidth/Height (включая скрытый контент). getBoundingClientRect() — позиция и размер относительно viewport (с учётом прокрутки).


Подробно

Три пары измерений:

  • clientWidth / clientHeight:

Контент + padding (БЕЗ border, БЕЗ scrollbar) const w = element.clientWidth;

  • offsetWidth / offsetHeight:

Контент + padding + border + scrollbar const w = element.offsetWidth;

  • scrollWidth / scrollHeight:

Вся ширина/высота контента (включая скрытый за пределами) const w = element.scrollWidth;

Визуально: ┌──────────────── offsetWidth ──────────────────┐ │ ┌──────────── clientWidth ────────────┐ │ │ │ │ sb │ │ │ ┌──────── content ────────────┐ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────┘ │ │ │ │ (padding) │ │ │ └──────────────────────────────────────┘ │ └──────────────────────────────────────────────┘ (border) (scrollbar)

getBoundingClientRect():

const rect = element.getBoundingClientRect(); console.log(rect.top); // от верха viewport console.log(rect.left); // от левого края viewport console.log(rect.width); // ширина элемента console.log(rect.height); // высота элемента console.log(rect.bottom); // rect.top + rect.height console.log(rect.right); // rect.left + rect.width

Важно: getBoundingClientRect() — ОТНОСИТЕЛЬНО VIEWPORT. Если страница прокручена — значения не включают прокрутку.

Прокрутка:

scrollTop — сколько прокручено сверху scrollLeft — сколько прокручено слева scrollTo(x, y) — программная прокрутка scrollBy(x, y) — относительная прокрутка

element.scrollIntoView({ behavior: 'smooth' }) — прокрутить к элементу


Ментальная модель

Элемент — как коробка в коробке. clientWidth — внутреннее пространство (контент + подкладка). offsetWidth — коробка целиком (с крышкой и стенками). scrollWidth — если внутри что-то торчит за пределы коробки. getBoundingClientRect — координаты коробки на столе (viewport).


Примеры

**Самый простой:**

javascript
const box = document.querySelector('.box');

console.log('client:', box.clientWidth, box.clientHeight);
console.log('offset:', box.offsetWidth, box.offsetHeight);
console.log('scroll:', box.scrollWidth, box.scrollHeight);

Базовые измерения: три пары размеров элемента.

**Простой:**

javascript
const button = document.querySelector('button');
const tooltip = document.querySelector('.tooltip');

function showTooltip() {
  const rect = button.getBoundingClientRect();

  tooltip.style.position = 'fixed';
  tooltip.style.left = rect.left + 'px';
  tooltip.style.top = (rect.bottom + 8) + 'px';
  tooltip.style.display = 'block';
}

button.addEventListener('click', showTooltip);

Позиционирование тултипа через getBoundingClientRect.

**Реальный пример:**

javascript
// Плавная прокрутка к секции
document.querySelectorAll('a[href^="#"]').forEach(link => {
  link.addEventListener('click', (e) => {
    e.preventDefault();
    const target = document.querySelector(link.getAttribute('href'));
    if (target) {
      target.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }
  });
});

// Бесконечная прокрутка
const sentinel = document.querySelector('#sentinel');
const observer = new IntersectionObserver((entries) => {
  if (entries[0].isIntersecting) {
    loadMoreItems();
  }
});
observer.observe(sentinel);

Реальные примеры: smooth scroll + IntersectionObserver для бесконечной прокрутки.


Частые ошибки

**Неправильно:** Путать clientWidth и offsetWidth

**Почему:** clientWidth не включает border и scrollbar. offsetWidth включает всё.

**Правильно:** client = контент + padding. offset = контент + padding + border + scrollbar.

**Неправильно:** Думать, что getBoundingClientRect учитывает прокрутку

**Почему:** getBoundingClientRect — от viewport. При прокрутке top/left меняются.

**Правильно:** Для позиции на странице: rect.top + window.scrollY.

**Неправильно:** Измерять элемент до его отображения

**Почему:** До рендеринга размеры = 0. Измеряйте после mounted/visible.

**Правильно:** Измеряйте после того, как элемент видим на странице.


Важно запомнить

  • clientWidth/Height: контент + padding
  • offsetWidth/Height: + border + scrollbar
  • scrollWidth/Height: включая скрытый контент
  • getBoundingClientRect: от viewport
  • scrollTop/scrollLeft: программная прокрутка
  • Измеряйте только видимые элементы

Связь

Назад: Вы знаете манипуляции с DOM (D1-D8) и события (DA1-DA9). Теперь вы учитесь точным измерениям.

Вперёд: Финальный урок (DA11) — MutationObserver, выделение текста и связь с Event Loop.

Материалы курса DOM Advanced — PROlab Academy.