Любой медиа-запрос можно выполнить в реальном времени с помощью JavaScript. Создать экземпляр объекта, который возвращал бы результат проверки Media Query или оповещал бы об изменении этого результата, можно при помощи метода
.matchMedia()
. Все современные браузеры уже реализовали этот метод
в объекте window
. Если же вам нужна поддержка старых браузеров, то можно воспользоваться полифилом matchMedia.js.
var mql = window.matchMedia("(min-width: 720px)");
if (mql.matches) {
// десктоп или планшет
} else {
// мобильник
}
Теперь, когда мы знаем как организовать ветвление, основываясь на результате выполнения медиа-запроса, подгрузить «тяжелые» стили и скрипты можно только если они действительно необходимы.
var Environment = (function () {
var _mqDesktop;
function getDesktopMediaQuery() {
return _mqDesktop ||
(_mqDesktop = window.matchMedia("(min-width: 720px)"));
}
function isDesktop() {
return !!(window.matchMedia && getDesktopMediaQuery().matches);
}
function once(mq, callback) {
function handler() {
mq.removeListener(handler);
callback();
}
mq.addListener(handler);
}
return {
/**
* Test the environment against “desktop” media query
*/
isDesktop: isDesktop,
/**
* Invoke callback when the environment becomes like “desktop”.
*/
waitForDesktop: function (callback) {
if (isDesktop()) {
callback();
} else {
once(getDesktopMediaQuery(), callback);
}
}
};
})();
Далее в коде приложения сделать вызов:
Environment.waitForDesktop(function () {
Modernizr.load([
"/styles/desktop.css",
"/scripts/desktop.js"
]);
});
Таким образом, файл стилей
/styles/desktop.css
и скрипт /scripts/desktop.js
загрузятся только когда ширина экрана будет больше 720 пикселей.
Из-за того, что файлы загружаются асинхронно появляется побочный эффект — нет никакой гарантии, что выполнение скрипта начнётся только после применения стилей. Например, габариты блока будут не верны или блок вообще может быть невидимым во время инициализации компоненты. Это нужно учесть и дождаться полной загрузки CSS файла с перерисовкой страницы.
Проверить, что файл стилей гарантировано применился можно с помощью специальных стилей-маркеров.
mobile.css:
.style-detector {
z-index: 1;
}
desktop.css:
@media (min-width: 720px) {
.style-detector {
z-index: 2;
}
}
А колбек обернуть в функцию, которая ожидает нужного значения свойства z-index
.
function waitUntil(value, cb) {
var body, detector = document.querySelector(".style-detector");
if (!detector) {
detector = document.createElement("div");
detector.className = "style-detector";
body = document.getElementsByTagName("body")[0];
body.insertBefore(detector, body.firstChild);
}
function getStyle(el, cssProperty) {
return (getComputedStyle !== "undefined") ?
getComputedStyle(el)[cssProperty] : el.currentStyle[cssProperty];
}
var i = 100; // timeout = 25 sec
(function loop() {
var v = getStyle(detector, "zIndex");
if (v != value) {
i = i - 1;
if (i >= 0) {
setTimeout(loop, 250);
} else {
cb();
}
} else {
cb();
}
}());
}
Полный код модуля доступен на Гитхабе.