Tim*_*mah 4 javascript css media-queries responsive
我一直在寻找一种轻量,灵活,跨浏览器的解决方案,以在JavaScript中访问CSS媒体查询,而不会在JavaScript代码中重复CSS断点。
CSS技巧发布了一个基于CSS3动画的解决方案,该解决方案似乎很有帮助,但是建议改用Enquire.js。
Enquire.js似乎仍然需要在脚本中对Media Query大小进行硬编码,例如
enquire.register("screen and (max-width:45em)", { // do stuff }
Run Code Online (Sandbox Code Playgroud)
问题
到目前为止,所有用于访问Java媒体查询的解决方案似乎都依赖于在脚本中硬编码的断点。如何以允许仅在CSS中定义断点而不依赖的方式访问断点.on('resize')?
尝试的解决方案
我已经制作了自己的版本,可以在IE9 +中使用,使用了一个隐藏元素,该元素使用该:content属性添加查询触发时想要的任何内容(与ZeroSixThree解决方案相同的起点):
的HTML
<body>
<p>Page content</p>
<span id="mobile-test"></span>
</body>
Run Code Online (Sandbox Code Playgroud)
的CSS
#mobile-test {
display:none;
content: 'mq-small';
}
@media screen only and (min-width: 25em) {
#mobile-test {
content: 'mq-medium';
}
}
@media screen only and (min-width: 40em) {
#mobile-test {
content: 'mq-large';
}
}
Run Code Online (Sandbox Code Playgroud)
使用jQuery的JavaScript
// Allow resizing to be assessed only after a delay, to avoid constant firing on resize.
var resize;
window.onresize = function() {
clearTimeout(resize);
// Call 'onResize' function after a set delay
resize = setTimeout(detectMediaQuery, 100);
};
// Collect the value of the 'content' property as a string, stripping the quotation marks
function detectMediaQuery() {
return $('#mobile-test').css('content').replace(/"/g, '');
}
// Finally, use the function to detect the current media query, irrespective of it's breakpoint value
$(window).on('resize load', function() {
if (detectMediaQuery() === 'mq-small') {
// Do stuff for small screens etc
}
});
Run Code Online (Sandbox Code Playgroud)
这样,Media Query的断点完全由CSS处理。如果您更改断点,则无需更新脚本。如何才能做到这一点?
尝试这个
const mq = window.matchMedia( "(min-width: 500px)" );
Run Code Online (Sandbox Code Playgroud)
matchs属性根据查询结果返回true或false,例如
if (mq.matches) {
// window width is at least 500px
} else {
// window width is less than 500px
}
Run Code Online (Sandbox Code Playgroud)
您还可以添加事件侦听器,该侦听器在检测到更改时将触发:
// media query event handler
if (matchMedia) {
const mq = window.matchMedia("(min-width: 500px)");
mq.addListener(WidthChange);
WidthChange(mq);
}
// media query change
function WidthChange(mq) {
if (mq.matches) {
// window width is at least 500px
} else {
// window width is less than 500px
}
}
Run Code Online (Sandbox Code Playgroud)
请参阅专家 David Walsh 发表的这篇文章,使用 CSS 媒体查询和 JavaScript 进行设备状态检测:
CSS
.state-indicator {
position: absolute;
top: -999em;
left: -999em;
}
.state-indicator:before { content: 'desktop'; }
/* small desktop */
@media all and (max-width: 1200px) {
.state-indicator:before { content: 'small-desktop'; }
}
/* tablet */
@media all and (max-width: 1024px) {
.state-indicator:before { content: 'tablet'; }
}
/* mobile phone */
@media all and (max-width: 768px) {
.state-indicator:before { content: 'mobile'; }
}
Run Code Online (Sandbox Code Playgroud)
JS
var state = window.getComputedStyle(
document.querySelector('.state-indicator'), ':before'
).getPropertyValue('content')
Run Code Online (Sandbox Code Playgroud)
另外,这是 javascript 大师 Nicholas C. Zakas 提出的一个聪明的解决方案:
// Test a media query.
// Example: if (isMedia("screen and (max-width:800px)"){}
// Copyright 2011 Nicholas C. Zakas. All rights reserved.
// Licensed under BSD License.
var isMedia = (function () {
var div;
return function (query) {
//if the <div> doesn't exist, create it and make sure it's hidden
if (!div) {
div = document.createElement("div");
div.id = "ncz1";
div.style.cssText = "position:absolute;top:-1000px";
document.body.insertBefore(div, document.body.firstChild);
}
div.innerHTML = "_<style media=\"" + query + "\"> #ncz1 { width: 1px; }</style>";
div.removeChild(div.firstChild);
return div.offsetWidth == 1;
};
})();
Run Code Online (Sandbox Code Playgroud)