JavaScript >> Javascript 文檔 >  >> Tags >> CSS

JavaScript 中的 CSS 媒體查詢,第 1 部分

2011 年初,我正在做一個項目,我在 JavaScript 中進行一些特徵檢測。一些修改導致了使用 CSS 媒體查詢會更好地工作的想法,所以我花了一些時間想出一個在 JavaScript 中使用 CSS 媒體查詢的函數。我的想法很簡單:如果我只是基於媒體查詢應用某些 CSS,我也只想基於媒體查詢運行某些 JavaScript。結果是以下函數,我首先將其作為 Gist 1 發布 去年三月:

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;    
    };
})();

這個函數背後的想法很簡單。我創建了一個 <style> media 的節點 屬性等於我正在測試的那個。在裡面,有一個 CSS 規則應用於 <div> 我所要做的就是檢查樣式是否已應用。我想避免瀏覽器檢測,所以不要使用 currentStylegetComputedStyle() ,我決定只更改 width 一個元素並使用 offsetWidth 檢查它 .

很快,我就有了這個功能的一個版本,幾乎可以在所有瀏覽器中使用。您可能已經猜到,Internet Explorer 6 和 7 是例外。在這些瀏覽器中,<style> 元素被視為 NoScope 元素 2 .當使用 innerHTML 將 HTML 注入頁面時,NoScope 元素是一個可怕的例外 或任何其他方式。如果所有 NoScope 元素是作為 HTML 字符串添加的第一個元素,它們將被有效地刪除。為了使用 NoScope 元素,您必須確保它不是 HTML 字符串的第一部分。因此,我將下劃線放在 <style> 之前 元素,然後將其刪除——誘使 Internet Explorer 6 和 7 按應有的方式應用該元素。其他瀏覽器沒有這個 NoScope 元素問題,但使用這種技術不會對它們產生負面影響(正如我之前所說,我試圖避免瀏覽器檢測)。

最後,你可以這樣使用函數:

if (isMedia("screen and (max-width:800px)"){
    //do something for the screen
}

if (isMedia("all and (orientation:portrait)")){
    //react to portrait mode
}

isMedia() 在我測試的所有瀏覽器(回到 Internet Explorer 6)中運行良好,因為它可以準確地檢測瀏覽器是否認為媒體查詢有效。因此,將不受支持的查詢傳遞給任何瀏覽器總是返回 false。例如,如果您使用“screen”,Internet Explorer 6 會返回 true,但如果使用更複雜的內容,則會返回 false。我認為這是可以接受的,因為其他媒體查詢中的任何 CSS 無論如何都不會應用於該瀏覽器。

CSSOM 視圖

CSS 對像模型 (CSSOM) 視圖規範 3 通過添加方法 matchMedia() 在 JavaScript 中添加對 CSS 媒體查詢的原生支持 , 到 window 目的。你傳入一個 CSS 媒體查詢並收到一個 MediaQueryList 目的。該對象包含兩個屬性:matches ,這是一個布爾值,指示 CSS 媒體查詢是否匹配當前視圖狀態,以及 media ,與傳入的字符串相同。例如:

var match = window.matchMedia("screen and (max-width:800px)");
console.log(match.media);     //"screen and (max-width:800px)"
console.log(match.matches);   //true or false

到目前為止,這個 API 並沒有提供比我的 Gist 更多的東西。不過,您可能想知道為什麼 matchMedia() 返回一個對象?畢竟,如果媒體不匹配,那有什麼用呢?答案有兩種方法:addListener()removeListener() .

這兩種方法允許您基於 CSS 媒體查詢與視圖狀態更改進行交互。例如,您可能希望在平板電腦切換到縱向模式時收到提醒。你可以這樣做:

var match = window.matchMedia("(orientation:portrait)");
match.addListener(function(match){
    if (match.media == "(orientation:portrait)") {
        //do something
    }
});

此代碼為媒體查詢添加了一個偵聽器。當查詢為當前視圖狀態為真時,監聽器被執行並且對應的MediaQueryList 對像被傳入。通過這種方式,您可以讓您的 JavaScript 與您的佈局一樣響應,而無需輪詢。因此,與我的 Gist 不同的是,此 API 允許您監控不斷變化的視圖狀態並相應地調整界面行為。

matchMedia() 方法適用於 Chrome、Safari 5.1+、Firefox 9+ 和適用於 iOS 5+ 的 Safari。這些代表我可以訪問並可以驗證的瀏覽器。 Internet Explorer 和 Opera 仍然不支持 matchMedia() 從他們的最新版本開始。

注意: WebKit 的實現有點問題,所以 matchesMediaQueryList 之後不更新 對像被創建並且查詢偵聽器不會觸發。希望這將很快得到解決。

結論

CSS 媒體查詢為 CSS 和 JavaScript 帶來了簡單的特徵檢測語法。我預計未來媒體查詢將成為 JavaScript 編碼的重要組成部分,提醒開發人員何時發生重大界面變化。沒有理由認為 Web 應用程序的行為不應該與佈局一樣具有響應性,而 CSS 媒體查詢在今天為我們提供了這種能力。

參考

  1. 檢測瀏覽器是否處於給定媒體模式的函數
  2. MSDN:innerHTML 屬性
  3. CSS 對像模型視圖
  4. matchMedia() MediaQueryList 未更新

Tutorial JavaScript 教程
  1. 什麼是 Node 為什麼你應該使用它。

  2. 自定義你的 roguelike 圖形圖塊集(使用 JavaScript)

  3. 四行 TypeScript 中的強類型 VueX 存儲

  4. 使用新的實驗性 useTransition Hook 實現 CSS 動畫

  5. JavaScript 異步編程和回調

  6. 代碼中的趣味性:通過玩樂來增強您的學習能力

  7. 支持和反對`let`

  1. 正則表達式模式僅匹配某些字符

  2. Advent.js🎅🏼| #22:這棵樹需要多少裝飾品?

  3. 為全棧 Web 開發人員提供的少量 Github 存儲庫

  4. 成為初級全棧 Web 開發人員的 10 分鐘路線圖

  5. 使用 NestJS 搭建 Node.js 服務器,包括 TypeScript 和 GraphQL

  6. JavaScript 複製到剪貼板:用 JavaScript 在 10 行代碼中將文本複製到剪貼板

  7. 在 javascript 中比較和過濾對像數組

  1. 一個簡單的 D3.js 面積圖

  2. JavaScript ResizeObserver |界面

  3. 使用 Express 處理 POST 請求

  4. 使用 Intersection Observer 響應粘性事件