Мы все знаем и любим мультимедийные запросы CSS, они значительно облегчают нашу жизнь, когда мы создаем адаптивные веб-сайты.

Теперь, во времена препроцессоров CSS, мы в основном используем переменные для наших медиа-запросов, чтобы синхронизировать их в нашем проекте:

$small:”(max-width: 500px)”;
$medium:”(min-width: 501px) and (max-width: 1200px)”;
$xlarge:”(min-width: 1920px)”;
.elem {
 background: red; // the default is large viewport
 
 @media #{$small}{ background: blue; }
 @media #{$medium}{ background: green; }
 @media #{$xlarge}{ background: green; }
}

Но что нам делать, если мы хотим использовать медиа-запросы в нашем javascript? обычным подозреваемым будет window.matchMedia, который вернет новый объект MediaQueryList, представляющий результаты анализа указанной строки медиа-запроса (документы MDN), например:

function windowWidthChange(mq) {
  if (mq.matches) {
    console.log('window width less than 500px');
  } else {
    console.log('window width is more than 500px');
  }
}
const $small = '(max-width: 500px)';
const mq = window.matchMedia($small);
mq.addListener(windowWidthChange);

Это прекрасно работает, но имеет основную проблему: нам нужно определить переменную $small в двух несвязанных файлах, javascript и sass, а в больших проектах с большим количеством файлов sass/js лучше всего сделать определить переменную один раз и использовать ее везде. если переменная изменяется в одном месте, мы хотим, чтобы она применялась везде.

Чтобы добиться этого (определить переменную один раз), мы можем использовать анимацию и событие animationend:

// SASS
$small:”(max-width: 500px)”;
$medium:”(min-width: 501px) and (max-width: 1200px)”;
$large:”(min-width: 1201) and (max-width: 1919px)”;
$xlarge:”(min-width: 1920px)”;
@keyframes small {
 from { clip: rect(1px, auto, auto, auto); } 
 to { clip: rect(0px, auto, auto, auto); }
}
@keyframes medium {
 from { clip: rect(1px, auto, auto, auto); } 
 to { clip: rect(0px, auto, auto, auto); }
}
@keyframes large {
 from { clip: rect(1px, auto, auto, auto); } 
 to { clip: rect(0px, auto, auto, auto); }
}
@keyframes xlarge {
 from { clip: rect(1px, auto, auto, auto); }
 to { clip: rect(0px, auto, auto, auto); }
}
body {
 animation-duration: 0.001s;
 animation-name: large;
 
 @media #{$small}{ animation-name: small; }
 @media #{$medium}{ animation-name: medium; }
 @media #{$xlarge}{ animation-name: xlarge; }
}
// JS
document.addEventListener(‘animationend’, (event) => {
  switch (event.animationName) {
    case ‘small’: console.log(‘small’); break;
    case ‘medium’: console.log(‘medium’); break;
    case ‘large’: console.log(‘large’); break;
    case ‘xlarge’: console.log(‘xlarge’); break;
  }
}, false);

При таком подходе мы получаем ту же функциональность, что и window.matchMedia, но мы определяем переменные только в коде sass, поэтому, если мы решим изменить наши медиа-запросы, изменение также будет применено к javascript, и наш проект будет будьте последовательны!