Мы все знаем и любим мультимедийные запросы 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, и наш проект будет будьте последовательны!