有无数的理由要求我们在任何时候都应该知道用户是使用的什么设备浏览我们的网站——宽屏,普通屏,平板,手机?知道这些特征,我们web应用的CSS和JavaScript才能同步做相应的操作。在给Mozilla Developer Networks改版设计的过程中,我发现使用CSS媒体查询(media queries)虽然非常的有效,但有时,JavaScript却不能及时知道用户浏览设备的状态。浏览网站的用户使用的是桌面电脑,还是平板,还是手机?这对于CSS来说很容易,但CSS却无法将这些信息告诉JavaScript。我发明了一种基于CSS媒体查询和z-index属性的方法,能告诉JavaScript用户当前使用的是什么屏幕,这样我能调整JavaScript的动作来响应这种屏幕尺寸。

CSS代码

首先最重要的还是CSS媒体查询代码。这里只是示例,我们创建了三个媒体查询规则(但不包括缺省的“all”),它能控制四种屏幕情况:桌面(这是缺省状态,不需要媒体查询规则),“小屏幕”,平板,手机。针对每一种屏幕,我们给它一种不同的z-index值,这个值我们可以用JavaScript检测到。我们把这个元素定位到屏幕外,这样它就不会显示出来;记住,它的作用就是存放z-index值,我们要用javaScript获取这个值。

/* 缺省屏幕 */
.state-indicator {
position: absolute;
top: -999em;
left: -999em; z-index: 1;
} /* 小屏幕 */
@media all and (max-width: 1200px) {
.state-indicator {
z-index: 2;
}
} /* 平板 */
@media all and (max-width: 1024px) {
.state-indicator {
z-index: 3;
}
} /* 手机 */
@media all and (max-width: 768px) {
.state-indicator {
z-index: 4;
}
}

每种z-index都在告诉我们的JavaScript当前的用户使用的是什么规格的屏幕。我们并不像知道用户究竟使用的是什么设备,因为你可以将浏览器宽度拉的很窄,但我们需要就是可视宽度,这样我们可以调整应用的布局。

JavaScript代码

也许你认为可以在DomContentLoaded时知道屏幕的大小,但我们需要实时知道屏幕的大小(因为用户会调整浏览器窗口的大小),我们需要有个方法获取当前窗口的属性:

// 创建状态指示元素
var indicator = document.createElement('div');
indicator.className = 'state-indicator';
document.body.appendChild(indicator); // 获取设备类别的方法
function getDeviceState() {
return parseInt(window.getComputedStyle(indicator).getPropertyValue('z-index'), 10);
}

使用这个方法,你就能检测出页面布局/js饰件中那些需要显示,那些需要隐藏。

if(getDeviceState() < 3) { // 如果是桌面电脑后小屏幕电脑
// 显示js饰件....
}

有人也许会认为这些数字太容易搞错,让代码很难维护。其实我们可以用一个对象来处理这种事情:

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

这样,你就一个写出更具可读性的逻辑判断:

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

也许使用CSS的伪元素的content属性是个更好的方法:

.state-indicator {
position: absolute;
top: -999em;
left: -999em;
}
.state-indicator:before { content: 'desktop'; } /* 小屏幕桌面 */
@media all and (max-width: 1200px) {
.state-indicator:before { content: 'small-desktop'; }
} /* 平板 */
@media all and (max-width: 1024px) {
.state-indicator:before { content: 'tablet'; }
} /* 手机 */
@media all and (max-width: 768px) {
.state-indicator:before { content: 'mobile'; }
}

用下面的JavaScript方法获取关键的内容:

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

如何组织这些代码全看你自己了。如果你有一个全局对象,例如window.configwindow.app等,你可以把这些方法放到里面。我倾向于模块化这些功能,你可以把它做成jQuery插件或JavaScript工具包。不管你如何实现,它们都是你可以信赖的、简单易用的检测用户设备的好方法。

更上一层楼

我们知道屏幕尺寸会发生变化——用户手工调整浏览器大型或手机用户调整了手机方向,所以,当这些事件发生时,我们需要让系统告诉我们。下面这段简单的代码估计是你需要的:

var lastDeviceState = getDeviceState();
window.addEventListener('resize', debounce(function() {
var state = getDeviceState();
if(state != lastDeviceState) {
// 保持当前的状态
lastDeviceState = state; // 宣告状态变化,通过自定义的DOM事件或JS 消息发布/订阅模式,
// 我喜欢后者,所有就假设使用了一个这样的工具库
publish('/device-state/change', [state]);
}
}, 20)); // 用法
subscribe('/device-state/change', function(state) {
if(state == 3) { // or "tablet", if you used the object }
});

注意,这里我使用了debounce方法来执行resize事件发生时的动作——这对于性能来说非常重要。是使用自定义DOM事件还是使用发布/订阅模式,你自由选择,因为都很简单。

我觉得这种方法非常的好。有人可能会指出使用matchMedia也可以有相同效果,但问题是你需要在CSS里和JavaScript里都使用媒体查询,而有些媒体查询语句可能会很复杂,甚至会成为你的噩梦,不如使用简单的z-index。也有人会说可以使用 window.innerWidth来判断,但这样JS里获取的属性和CSS里的媒体查询就需要相互转换了,同样也会成为你的恶魔。我的方法的好处就在于你可以用它判断其他类型的媒体查询属性,例如检查手机是横向(landscape)还是竖向(portrait)。

不管怎样,你可以试一下,告诉我你的感觉!

巧妙使用CSS媒体查询(Media Queries)和JavaScript判断浏览器设备类型的好方法的更多相关文章

  1. css3的媒体查询(Media Queries)

    我今天就总结一下响应式设计的核心CSS技术Media(媒体查询器)的用法. 先看一个简单的例子: <link rel="stylesheet" media="scr ...

  2. 媒体查询Media Queries详解

    @media 标签可以说是响应式网页的开发基础.其主要由媒体类型(Media Type)和 媒体特性(Media Query)两部分组成. Media Type 设定后面规则生效的展示类型,包括all ...

  3. CSS3的媒体查询(Media Queries)与移动设备显示尺寸大全

    媒体查询介绍 我今天就总结一下响应式设计的核心CSS技术Media(媒体查询器)的用法. 先看一个简单的例子: <link rel="stylesheet" media=&q ...

  4. CSS3媒体查询(Media Queries)介绍

    媒体类型 all 所有设备 screen 电脑显示器 handheld 便携设备 tv 电视类型设备 print 打印用纸打印预览视图 关键字 and not(排除某种设备) only(限定某种设备) ...

  5. CSS 媒体查询@media

    1. 概述 1.1 定义 @media可以针对不同的屏幕尺寸(媒体类型)设置不同的样式,在响应式页面中,@media非常有用.重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面. 1. ...

  6. 怎样使用CSS3媒体查询(Media Queries)制作响应式网站

    自本周开始博主将开始同大家一起研究响应式web设计,CSS3 Media Queries是入门,本周更新,博主将给大家分享media queries的一些常用的用法及注意事项. Media Queri ...

  7. CSS媒体查询(@media)

    @media only screen and (max-width: 500px) { .gridmenu { width:100%; } .gridmain { width:100%; } .gri ...

  8. CSS3 之媒体查询Media Query

    Media Queries是CSS3有关媒体查询的属性,有了CSS3 之媒体查询Media Queries就可以进行媒体查询,针对每个不同的媒体进行不同的样式编写.传说中的Web响应式布局就可以毫无压 ...

  9. 详解css媒体查询

    简介 媒体查询(Media Queries)早在在css2时代就存在,经过css3的洗礼后变得更加强大bootstrap的响应式特性就是从此而来的. 简单的来讲媒体查询是一种用于修饰css何时起作用的 ...

随机推荐

  1. [Oracle]如何查看一个数据文件是否是自动扩展

    开始 SQL> col file_id format 99SQL> col file_name format a50SQL> col tablespace_name format a ...

  2. OpenStack入门篇(九)之nova服务(控制节点)的部署与测试

    1.Nova介绍 Nova是openstack最早的两块模块之一,另一个是对象存储swift.在openstack体系中一个叫做计算节点,一个叫做控制节点.这个主要和nova相关,我们把安装为计算节点 ...

  3. vivado与modelsim的联合仿真

    转载: 一.在vivado中设置modelsim(即第三方仿真工具)的安装路径.在vivado菜单中选择“Tools”——>“Options...”,选择“General”选项卡,将滚动条拉倒最 ...

  4. guacamole实现RDP的下载

    1. 配置说明 1.1 主要特别配置以下三项 enable-drive 默认情况下禁用文件传输,但启用文件传输后,RDP用户可以将文件传输到持久存在于Guacamole服务器上的虚拟驱动器.通过将此参 ...

  5. [Luogu4182][USACO18JAN]Lifeguards P[单调队列]

    题意 给定 \(n\) 个区间,必须去掉其中的 \(K\) 个,询问能够保留的区间并的最大值. \(n \leq 10^5\ ,K \leq 100\) . 分析 定义状态 \(f_{i,j}\) 表 ...

  6. MySQL ZIP Archive 5.7.17 安装方法

    1.下载 2.解压缩 3.创建/修改配置文件 在MySQL安装目录下,新建my.ini,内容如下参考 [mysql] # 设置mysql客户端默认字符集 default-character-set=u ...

  7. STM平台增加性能测试/稳定性测试部分【二】

    [一]方案 基本上测试针对产品的各项方案大体是如下的: 如上所示,针对产品的性能测试主要步骤如下: 1.造数据,在产品业务流上,产生所需的数据,数据量以(稳定性或者压测指标确定) 2.根据步骤1,设定 ...

  8. Ubuntu安装Oh My Zsh

    1. 安装ZSH sudo apt-get install zsh 安装完后需要注销或重启才能生效.注销或重启后打开终端,会出现ZSH的界面,选择(2) 2. 安装Oh My Zsh sh -c &q ...

  9. MySQL事务及其实现

    事务定义 事务是访问并更新数据库中各个数据项的一个程序执行单元.在事务操作中,要不都做修改,要么都不做. 事务特性 事务具有ACID四个特性,分别是:原子性(Atomicity).一致性(Consis ...

  10. ats Linux路由器上内联

    路由设置假定客户端集在单个物理接口后面的不同网络上. 出于本例的目的,我们将假设: 客户端位于172.28.56.0/24网络上路由器连接网络172.28.56.0/24和192.168.1.0/24 ...