css 媒体查询,设备宽度_使用CSS媒体查询和JavaScript进行设备状态检测

css 媒体查询,设备宽度

Being able to detect device state at any given moment is important for any number of reasons and so it's important that web app CSS and JavaScript are in sync with each other. In working on the Mozilla Developer Networks' redesign, I found that our many media queries, although helpful, sometimes left JavaScript in the dark about the device state. Is the user viewing the site in desktop, tablet, or phone screen size? Easy from a CSS perspective but CSS doesn't directly speak with JavaScript. I've created a system based on media queries and z-index which can tell me which media query the user is viewing the site in at any given time, so that I can make adjustments to dynamic functionality whenever I want!

出于多种原因,能够在任何给定时刻检测设备状态非常重要,因此使Web应用程序CSS和JavaScript相互同步非常重要。 在进行Mozilla开发人员网络的重新设计时,我发现我们的许多媒体查询虽然很有帮助,但有时会使JavaScript陷入设备状态的黑暗之中。 用户是以台式机,平板电脑还是手机屏幕尺寸查看网站? 从CSS的角度来看很容易,但是CSS不能直接与JavaScript对话。 我创建了一个基于媒体查询和z-index ,该系统可以告诉我用户在任何给定时间正在查看哪个媒体查询,以便可以随时调整动态功能!

CSS (The CSS)

The first step is creating media queries important to your application and goals. For the sake of an example, we'll create three new media queries (not including the default "all") which will accommodate four states: desktop (default, doesn't require a media query), "small desktop", tablet, and phone. With each of those states, we'll set a different z-index on an element we'll use to detect the state. The element will be positioned well offscreen so that's not visible; remember, it's only purpose is holding a z-index value that we can retrieve via JavaScript:

第一步是创建对您的应用程序和目标很重要的媒体查询。 举例来说,我们将创建三个新的媒体查询(不包括默认的“全部”),这些查询将包含四个状态:台式机(默认,不需要媒体查询),“小型桌面”,平板电脑,和电话。 对于每个状态,我们将在用于检测状态的元素上设置不同的z-index 。 元素将被放置在屏幕之外,因此不可见; 记住,唯一的目的是保存一个z-index值,该值可以通过JavaScript检索:

/* default state */
.state-indicator {
    position: absolute;
    top: -999em;
    left: -999em;

    z-index: 1;
}

/* small desktop */
@media all and (max-width: 1200px) {
    .state-indicator {
        z-index: 2;
    }
}

/* tablet */
@media all and (max-width: 1024px) {
    .state-indicator {
        z-index: 3;
    }
}

/* mobile phone */
@media all and (max-width: 768px) {
    .state-indicator {
        z-index: 4;
    }
}


Each of those z-index numbers will indicate to our JavaScript code that we're in a given device size at that time. We aren't trying to detect that the user is giving a given device, as the user could simply have their desktop window in a narrow state, but it does give us information about screen real estate for the sake of our web app layout.

每个z-index数字都将向我们JavaScript代码指示我们当时处于给定的设备尺寸。 我们并没有试图检测用户正在提供给定的设备,因为用户可能只是将其桌面窗口置于狭窄的状态,但是为了我们的Web应用程序布局,它的确为我们提供了有关屏幕空间的信息。

JavaScript (The JavaScript)

You'll likely want to know the screen size upon DomContentLoaded but since you may want to query for it at any time (since the user could resize their window), we'll require a function be called to get the state any time it is requested:

您可能想知道DomContentLoaded的屏幕大小,但是由于您可能想随时查询它(因为用户可以调整其窗口大小),因此我们将需要调用一个函数以在任何时候获取状态。要求:

// Create the state-indicator element
var indicator = document.createElement('div');
indicator.className = 'state-indicator';
document.body.appendChild(indicator);

// Create a method which returns device state
function getDeviceState() {
    return parseInt(window.getComputedStyle(indicator).getPropertyValue('z-index'), 10);
}


So let's say you want to usage this system to determine if a widget should initially display or should be hidden:

因此,假设您要使用此系统来确定窗口小部件是应该最初显示还是应该隐藏:

if(getDeviceState() < 3) { // If desktop or small desktop
    // Show the widget....
}


One could argue that relying on those number keys could be confusing or hard to maintain, so you could use an object to deal with that:

有人可能会争辩说,依靠这些数字键可能会造成混乱或难以维护,因此您可以使用一个对象来处理:

function getDeviceState() {
    var index = parseInt(window.getComputedStyle(indicator).getPropertyValue('z-index'), 10);

    var states = {
        2: 'small-desktop',
        3: 'tablet',
        4: 'phone'
    };

    return states[index] || 'desktop';
}


In this case, you could create more English-friendly conditionals:

在这种情况下,您可以创建更多的英语友好条件:

if(getDeviceState() == 'tablet') {
    // Do whatever
}


Possibly the better option is using pseudo-element content with CSS and JavaScript :

可能更好的选择是将伪元素内容与CSS和JavaScript结合使用:


.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'; }
}


That key could then be retrieved with this JavaScript:

然后可以使用以下JavaScript检索该键:


var state = window.getComputedStyle(
    document.querySelector('.state-indicator'), ':before'
).getPropertyValue('content')



How you organize this code is also up to you. If you have one global object where you pin methods and properties (like a window.config or window.app global or similar), you can pin the method on that. I prefer using AMD format modules but to each their own. You could add it as a plugin to jQuery or whichever JavaScript library you use. Regardless of how you implement, you now have reliable, easy to use device state detection on the client side thanks to media queries!

您如何组织此代码也取决于您。 如果您有一个全局对象在其中固定方法和属性(例如window.configwindow.app全局或类似对象),则可以在其上固定方法。 我更喜欢使用AMD格式模块,但是每个模块都使用它们。 您可以将其添加为jQuery插件或您使用的任何JavaScript库。 无论您如何实现,由于有了媒体查询,您现在都可以在客户端进行可靠,易于使用的设备状态检测!

进一步努力 (Furthering the Effort)

We know that screen resizes happen, whether manual window resizing on desktop or via orientation change on mobile devices, so we may want some type of event system to announce those changes when they occur. That's as simple as you would expect:

我们知道,无论是在桌面上手动调整窗口大小还是通过移动设备上的方向更改,都会发生屏幕调整大小,因此我们可能希望某些类型的事件系统在发生更改时宣布这些更改。 就像您期望的那样简单:

var lastDeviceState = getDeviceState();
window.addEventListener('resize', debounce(function() {
    var state = getDeviceState();
    if(state != lastDeviceState) {
        // Save the new state as current
        lastDeviceState = state;

        // Announce the state change, either by a custom DOM event or via JS pub/sub
        // Since I'm in love with pub/sub, I'll assume we have a pub/sub lib available
        publish('/device-state/change', [state]);
    }
}, 20));

// Usage
subscribe('/device-state/change', function(state) {
    if(state == 3) { // or "tablet", if you used the object

    }
});


Note that I've used function debouncing to limit the rate at which the resize method is fired -- that's incredibly important for the sake of performance. Whether you use pub/sub or custom DOM events is up to you, but the point is that creating a state change listener is easy!

请注意,我已经使用函数反跳来限制触发resize方法的速率-这对于提高性能非常重要。 是否使用发布/订阅事件或自定义DOM事件取决于您,但是关键是创建状态更改侦听器很容易!

I love this system of resize and device state management. Some will point out matchMedia as an option but the problem with that is needing to have the media queries in both the CSS and the JavaScript and since media queries can be complex, that seems like more of maintenance nightmare than simply using z-index codes. People could argue than one could use window.innerWidth measurements but that's simply trying to translate media queries to JS conditionals and that's a nightmare too. What's also nice about this is that you can use the same type of system for any type media query signifier, like checking for portrait or landscape orientation.

我喜欢这种调整大小和设备状态管理的系统。 有人会指出matchMedia是一个选项,但是这样做的问题是需要在CSS和JavaScript中都包含媒体查询,并且由于媒体查询可能很复杂,这似乎比不仅仅使用z-index代码更像是一场维护噩梦。 人们可能会争辩说使用window.innerWidth量值会比别人更争论,但这只是试图将媒体查询转换为JS条件,这也是一场噩梦。 这样做的好处还在于,您可以对任何类型的媒体查询指示符使用相同类型的系统,例如检查portraitlandscape

In any event, give it a try and let me know what you think!

无论如何,请尝试一下,让我知道您的想法!

翻译自: https://davidwalsh.name/device-state-detection-css-media-queries-javascript

css 媒体查询,设备宽度

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值