Media queries и matchMedia

Media queries в контексте веб-разработки позволяют применять различные стили и анимации в зависимости от характеристик устройства, таких как ширина экрана, ориентация или разрешение. В сочетании с библиотекой GSAP это открывает возможности для создания адаптивных анимаций, которые корректно работают на разных устройствах.


Основы matchMedia

JavaScript предоставляет метод window.matchMedia(), который позволяет проверять соответствие текущего состояния окна определенному медиазапросу. Синтаксис:

const mediaQuery = window.matchMedia("(min-width: 768px)");
  • mediaQuery.matches возвращает true, если условие медиазапроса выполнено.
  • mediaQuery.addEventListener("change", callback) позволяет отслеживать изменения состояния медиазапроса.

Пример базового использования:

const mq = window.matchMedia("(max-width: 600px)");

function handleWidthChange(e) {
    if (e.matches) {
        console.log("Экран меньше или равен 600px");
    } else {
        console.log("Экран больше 600px");
    }
}

mq.addEventListener("change", handleWidthChange);
handleWidthChange(mq);

Интеграция с GSAP

GSAP предлагает собственный метод gsap.matchMedia(), который упрощает работу с медиазапросами и автоматическое управление анимациями при изменении размеров экрана.

const mm = gsap.matchMedia();

mm.add("(min-width: 768px)", () => {
    gsap.to(".box", { x: 400, duration: 1 });
});
  • Первый аргумент — медиазапрос.
  • Второй аргумент — функция, которая выполняется только при совпадении медиазапроса.
  • Все анимации внутри функции автоматически удаляются при изменении состояния медиазапроса на противоположное, что предотвращает конфликт анимаций.

Применение нескольких медиазапросов

GSAP позволяет одновременно регистрировать несколько медиазапросов, что полезно для сложных адаптивных интерфейсов:

const mm = gsap.matchMedia();

mm.add({
    "(min-width: 1200px)": () => gsap.to(".box", { x: 500 }),
    "(min-width: 768px) and (max-width: 1199px)": () => gsap.to(".box", { x: 300 }),
    "(max-width: 767px)": () => gsap.to(".box", { x: 100 })
});
  • Каждое условие автоматически проверяется при инициализации и при изменении размеров окна.
  • GSAP управляет анимациями, чтобы не возникало конфликтов при переключении между медиазапросами.

Отмена анимаций при смене состояния

GSAP предоставляет возможность автоматически очищать анимации при несоответствии медиазапроса. Для этого используется объект context:

const mm = gsap.matchMedia();

mm.add("(max-width: 600px)", (context) => {
    let tl = gsap.timeline();
    tl.to(".box", { x: 200, duration: 1 });
    context.add(() => tl.kill());
});
  • context.add() регистрирует функцию очистки, которая вызывается при выходе из медиазапроса.
  • Это предотвращает накопление анимаций и утечки памяти.

Адаптивные ScrollTrigger-анимации

GSAP ScrollTrigger тесно интегрируется с matchMedia. Можно создавать анимации, которые зависят от размеров экрана:

const mm = gsap.matchMedia();

mm.add("(min-width: 1024px)", () => {
    gsap.to(".panel", {
        scrollTrigger: {
            trigger: ".panel",
            start: "top center",
            end: "bottom top",
            scrub: true
        },
        x: 500
    });
});

mm.add("(max-width: 1023px)", () => {
    gsap.to(".panel", {
        scrollTrigger: {
            trigger: ".panel",
            start: "top center",
            end: "bottom top",
            scrub: true
        },
        x: 200
    });
});
  • Разные анимации активируются в зависимости от ширины экрана.
  • ScrollTrigger корректно уничтожается при смене медиазапроса.

Динамическое обновление при изменении окна

GSAP автоматически следит за изменением размеров окна, когда используется gsap.matchMedia(). Дополнительно можно использовать window.matchMedia() для кастомных проверок или сложных условий:

const mq = window.matchMedia("(orientation: portrait)");

mq.addEventListener("change", (e) => {
    if (e.matches) {
        gsap.to(".box", { rotation: 0 });
    } else {
        gsap.to(".box", { rotation: 90 });
    }
});
  • Позволяет создавать адаптивные анимации не только по ширине, но и по ориентации, плотности пикселей и другим характеристикам.

Рекомендации по организации кода

  1. Все анимации, зависящие от медиазапросов, помещать внутрь gsap.matchMedia().
  2. Использовать context.add() для очистки анимаций при выходе из медиазапроса.
  3. Разделять медиазапросы по логическим блокам: мобильные, планшеты, десктопы.
  4. Для ScrollTrigger всегда проверять пересоздание триггеров при изменении состояния медиазапроса.

Использование matchMedia вместе с GSAP позволяет создавать гибкие, адаптивные анимации, которые автоматически реагируют на размеры экрана, ориентацию устройства и другие характеристики, обеспечивая высокое качество пользовательского интерфейса на любых устройствах.