Кратко
Размеры элементов: 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).
Примеры
**Самый простой:**
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);Базовые измерения: три пары размеров элемента.
**Простой:**
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.
**Реальный пример:**
// Плавная прокрутка к секции
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.