有無數的理由要求咱們在任什麼時候候都應該知道用戶是使用的什麼設備瀏覽咱們的網站——寬屏,普通屏,平板,手機?知道這些特徵,咱們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獲取這個值。java
/* 缺省屏幕 */ .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當前的用戶使用的是什麼規格的屏幕。咱們並不像知道用戶究竟使用的是什麼設備,由於你能夠將瀏覽器寬度拉的很窄,但咱們須要就是可視寬度,這樣咱們能夠調整應用的佈局。web
也許你認爲能夠在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飾件中那些須要顯示,那些須要隱藏。app
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.config
或window.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
)。
無論怎樣,你能夠試一下,告訴我你的感受!