我有一个JS变量来控制页面的样式。我希望它根据屏幕分辨率进行更改。如何使其取决于CSS媒体查询的结果。
我知道我可以直接在JS中检查屏幕分辨率,但是我想将所有样式决定保留在CSS中,而不是将其散布在JS和CSS文件中。
为避免XY问题:我正在使用Leaflet,而JS变量决定列出可用图层的任何地图控制面板是否折叠。应该在小屏幕(移动设备)上折叠它,而不应该在大屏幕(适当的显示器)上折叠它。
相关代码在下面
html,
body {
height: 100%;
margin: 0;
}
#map {
width: 600px;
height: 400px;
}
@media (min-width: 1000px) {
#map {
width: 1000px;
height: 900px;
}
}
<!DOCTYPE html>
<html>
<!--based on https://leafletjs.com/examples/layers-control/ example -->
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.3/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.3.3/dist/leaflet.js" integrity="sha512-tAGcCfR4Sc5ZP5ZoVz0quoZDYX5aCtEm/eu1KhSLj2c9eFrylXZknQYmxUssFaVJKvvc0dJQixhGjG2yXWiV9Q==" crossorigin=""></script>
<link rel="stylesheet" href="example.css" />
</head>
<body>
<div id='map'></div>
<script>
var positron = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', {
attribution: '#{openstreetmap_copyright_notice}, basemap: © <a href=\"http://cartodb.com/attributions\">CartoDB</a>',
subdomains: 'abcd',
maxZoom: 19
}),
osmcarto = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
});
var map = L.map('map', {
center: [39.73, -104.99],
zoom: 10,
layers: [positron]
});
var baseLayers = {
"positron": positron,
"osm-carto": osmcarto
};
L.control.layers(baseLayers, {}, {
collapsed: false
}).addTo(map); //false/true should be specified by CSS
</script>
</body>
</html>
答案 0 :(得分:4)
您可以使用matchMedia
进行一次检查,或者一次性(或更有用地)使用回调(有关回调选项here的更多信息):
window.matchMedia("(min-width: 1000px)").addListener(function(e) {
if (e.matches) {
// The window currently matches the query
} else {
// It doesn't
}
});
为避免在JavaScript中重复查询文本,您可以搜索document.styleSheets
并使用其media
属性。可能不会很有趣,但是我无法想象有其他方法来避免重复媒体查询。
例如,这使用它发现的第一个screen and
规则(jsFiddle):
// Find the rule
const rule = Array.from(document.styleSheets).reduce((found, sheet) => {
return found || Array.from(sheet.cssRules || sheet.rules).find(rule => {
return rule.conditionText && rule.conditionText.startsWith("screen and ");
});
}, null);
if (rule) {
const query = rule.conditionText.substring(11);
console.log("rule found, setting listener for: " + query);
window.matchMedia(query).addListener(function(e) {
console.log("matches? ", e.matches);
});
} else {
console.log("No rule found");
}
自然地,您需要等待通过link
元素加载的所有样式表都首先加载。
答案 1 :(得分:4)
漂亮的解决方案,但这并不意味着不对JS中的任何宽度属性进行硬编码。
在页面上添加一个虚拟的不可见元素。
<div id="dummy"></div>
#dummy::after {
display: none;
content: 'false';
}
@media (min-width: 1000px) {
#dummy::after {
content: 'true';
}
}
然后在JS中读取content
的值:
var isBigScreen = window.getComputedStyle(
document.querySelector('#dummy'), ':after'
).getPropertyValue('content');
isBigScreen
将是"true"
或"false"
。如果屏幕尺寸发生变化,您可能需要添加一些代码以重新检查。
if(isCollapsed === '"false"') {
isCollapsed = false;
} else {
isCollapsed = true;
}
可用于将其转换为标准布尔值。
答案 2 :(得分:2)
我唯一想到的方法是在CSS中设置某种样式,然后在Javascript中检查该样式。
例如类似于document.getElementById('map').style.width === '1000px'