Определение размера экрана

Получение размеров viewport и реакция на изменение размера окна — window.innerWidth, ResizeObserver, matchMedia.

Задача

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

Решение

Текущий размер viewport:

const width  = window.innerWidth;   // ширина viewport (без прокрутки)
const height = window.innerHeight;  // высота viewport

// Размер документа (включая скрытое за прокруткой)
const scrollWidth  = document.documentElement.scrollWidth;
const scrollHeight = document.documentElement.scrollHeight;

Реакция на resize (с throttle):

function onResize() {
  console.log('Ширина:', window.innerWidth);

  if (window.innerWidth < 768) {
    // мобильное поведение
  } else {
    // десктопное поведение
  }
}

let resizeTimer;
window.addEventListener('resize', () => {
  clearTimeout(resizeTimer);
  resizeTimer = setTimeout(onResize, 150);
});

matchMedia — предпочтительный способ:

const mql = window.matchMedia('(max-width: 768px)');

function handleBreakpoint(event) {
  if (event.matches) {
    console.log('Мобильный');
  } else {
    console.log('Десктоп');
  }
}

handleBreakpoint(mql);                    // вызов при инициализации
mql.addEventListener('change', handleBreakpoint); // слушать изменения

ResizeObserver — для конкретного элемента:

const box = document.getElementById('myBox');

const ro = new ResizeObserver((entries) => {
  for (const entry of entries) {
    const { width, height } = entry.contentRect;
    console.log(`Элемент: ${width}x${height}`);
  }
});

ro.observe(box);
// Отписка: ro.unobserve(box) или ro.disconnect()

React-хук useWindowSize:

import { useState, useEffect } from 'react';

function useWindowSize() {
  const [size, setSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight,
  });

  useEffect(() => {
    const handler = () => setSize({ width: window.innerWidth, height: window.innerHeight });
    window.addEventListener('resize', handler, { passive: true });
    return  => window.removeEventListener('resize', handler);
  }, );

  return size;
}

Ключевые моменты

  • matchMedia предпочтительнее innerWidth для брейкпоинтов — синхронизирован с CSS media query.
  • ResizeObserver — для отслеживания размера конкретного элемента (не viewport); заменяет resize для компонентного подхода.
  • Throttle resize обработчика — событие стреляет очень часто при ресайзе окна.
  • В SSR/Next.js — проверяй typeof window !== 'undefined' перед обращением к window.

Связанные рецепты / темы