1. 程式人生 > >使用window.matchMedia()匹配多個CSS媒體查詢

使用window.matchMedia()匹配多個CSS媒體查詢

一個常見的問題是如何使用它window.matchMedia() 來對多個CSS媒體查詢做出反應。在教程,我們快速概述 並使用它來響應單個CSS媒體查詢更改:window.matchMedia()

1

2

3

4

6

7

8

9

10

11

12

13

<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">function maxwidth800action(mql){</font></font><font></font><font style=

"vertical-align: inherit;"><font style="vertical-align: inherit;">

if(mql.matches){</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

console.log(“您的視窗是800px或更低”)</font></font><font></font><font style=

"vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

其他{</font></font><font></font><font style="vertical-align: inherit;"

><font style="vertical-align: inherit;">

console.log(“你的視窗大於800px”)</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font>

<font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

var mql = window.matchMedia(“screen and(max-width:800px)”)</font></font><font></font>

<font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

maxwidth800action(mql)//在執行時呼叫maxwidth800action()</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

mql.addListener(maxwidth800action)//每當觸發媒體查詢時呼叫maxwidth800action()</font></font>

在這裡,我們只監視一個CSS媒體查詢window.matchMedia(),即“ screen and (max-width: 800px)”,並在瀏覽器跨越該閾值時作出反應。

 響應多個CSS媒體查詢

為了響應使用多個CSS媒體查詢window.matchMedia(),我們基本上只是多次重複上述一個媒體查詢的藍圖。為了簡化程式碼,我們可以先使用陣列儲存所有window.matchMedia()查詢,然後使用for迴圈來呼叫處理所有查詢的單個函式。讓我們看看現在:

1

2

3

4

6

7

8

9

10

11

12

13

14

15

16

<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">var mqls = [// window.matchMedia()查詢列表</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

window.matchMedia(“(max-width:860px)”),</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

window.matchMedia(“(max-width:600px)”),</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

window.matchMedia(“(max-height:500px)”)</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

]</font></font><font></font>

<font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

function mediaqueryresponse(mql){</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

document.getElementById(“match1”)。innerHTML = mqls [0] .matches // width:860px媒體匹配?</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

document.getElementById(“match2”)。innerHTML = mqls [1] .matches // width:600px媒體匹配?</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

document.getElementById(“match3”)。innerHTML = mqls [2] .matches // height:500px媒體匹配?</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font>

<font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

forvar i = 0; i <mqls.length; i ++){//迴圈查詢</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

mediaqueryresponse(mqls [i])//在執行時顯式呼叫處理函式</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

mqls [i] .addListener(mediaqueryresponse)//每當觸發媒體查詢時呼叫處理函式</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font>

單擊此處檢視上述例項示例 - 在水平和垂直調整瀏覽器視窗大小時,將顯示不同的布林值,以反映當前匹配的媒體查詢。

我們現在有了連線多個媒體查詢的基本模式window.matchMedia(),雖然像很多東西一樣,魔鬼在細節中。當我們有一個響應所有媒體查詢的處理函式時,它意味著將多次呼叫此函式。這本身不是問題,實際上是設計的。在上面的示例中,處理函式window.matchMedia() 連線到3個不同的window.matchMedia()查詢,因此稱為以下次數:

  • 頁面首次載入時三次,每次處理頁面首次載入時可能匹配的每個查詢

  • 每次滿足輸入查詢之一的閾值時。如果使用者將瀏覽器的大小從900px調整為860px,然後調整為700px,則(max-width: 860px)當瀏覽器超過860px閾值時,將觸發一次查詢“ ”。將視窗大小調整為900px會再次觸發相同的查詢。

雖然多次呼叫我們的處理函式是為了處理我們的所有window.matchMedia() 查詢,但您可能不希望在每次呼叫期間執行此函式內的所有內容,至少為了提高效率。在上面的示例中,當匹配“ (max-width: 860px)”時,執行函式內的所有3行,而不是僅將“ #match1”元素設定為相應的布林值的行。這可以通過基於觸發函式的媒體查詢選擇性地執行程式碼來避免,這是我們接下來要看的。

- 找出window.matchMedia()觸發處理函式的查詢

使用單個函式處理所有window.matchMedia() 查詢匹配,有用 - 如果不是必要的話 - 有時可以確定哪個確切的查詢觸發了該函式。這與簡單地確定查詢是否成功匹配不同,我們可以使用matches儲存在陣列中的每個查詢的屬性輕鬆找出:

1

2

3

4

6

7

8

9

10

11

<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">function mediaqueryresponse(mql){</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

if(mqls [0] .matches){//在寬度:860px媒體查詢匹配時執行某些操作</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

// 做一點事</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

if(mqls [1] .matches){//在寬度:600px媒體查詢匹配時執行某些操作</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

// 做一點事</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

if(mqls [2] .matches){//在高度:500px媒體查詢匹配時執行某些操作</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

// 做一點事</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font>

為了確定哪個window.matchMedia()查詢實際觸發了處理函式,我們需要不僅檢查matches屬性,還要檢視media 傳入MediaQueryList 物件的屬性,它返回觸發查詢列表的序列化字串。在處理函式中,MediaQueryList 物件作為函式的第一個引數傳遞,或者在本例中為紅色引數:

1

2

3

<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">function mediaqueryresponse(mql){</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

console.log(mql.media)//返回“(max-width:860px)”例如</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font>

為了使事情稍微複雜化mediaMediaQueryList 物件屬性的返回值 在非IE(IE11)和IE瀏覽器之間略有不同。鑑於以下window.matchMedia()查詢,例如:

1

<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">var mql = window.matchMedia(“(max-width:860px)”)</font></font>

在非IE瀏覽器中,mql.media返回完全“ (max-width: 860px)”,而在IE中,它返回“ all and (max-width:860px)" 而不是。所以IE返回不同的是以下內容:

  • all在缺少查詢中指定的媒體的情況下,在字串前面新增“ ”的媒體

  • 刪除每個屬性和屬性值之間的任何空格,因此“ max-width:860px”中沒有空格。

media 用一些正則表示式探測屬性時,我們可以均衡這些差異。以下window.matchMedia()處理函式根據匹配window.matchMedia()mqls陣列中的哪個查詢列表 有選擇地執行不同的程式碼:

1

2

3

4

6

7

8

9

10

11

12

13

14

15

16

17

<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">var mqls = [// window.matchMedia()查詢列表</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

window.matchMedia(“(max-width:860px)”),</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

window.matchMedia(“(max-width:600px)”),</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

window.matchMedia(“(max-height:500px)”)</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

]</font></font><font></font>

<font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

function mediaqueryresponse(mql){</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

if(/ \(max-width:\ s * 860px \)/。test(mql.media)){//何時觸發“(max-width:860px)”查詢</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

//做一點事。</font><font style="vertical-align: inherit;">探測mql.matches以檢視是否實際滿足查詢條件</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

else if(/ \(max-width:\ s * 600px \)/。test(mql.media)){//當觸發“(max-width:600px)”查詢時</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

//做一點事。</font><font style="vertical-align: inherit;">探測mql.matches以檢視是否實際滿足查詢條件</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

else if(/ \(max-height:\ s * 500px \)/。test(mql.media)){//當“(max-height:500px)”查詢被觸發時</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

//做一點事。</font><font style="vertical-align: inherit;">探測mql.matches以檢視是否實際滿足查詢條件</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font>

media首先在處理函式內檢查屬性,確保只根據觸發處理程式的媒體查詢執行函式體的特定部分。結果類似於為每個window.matchMedia() 查詢定義單獨的函式,具有更易於管理的單個函式。然而,它沒有缺點。CSS媒體查詢很多時候會在範圍上重疊,因此針對一個查詢的程式碼也會針對另一個查詢進行測試。通過基於傳入window.matchMedia()查詢對功能程式碼進行分段,每個塊都成為互斥區域,無法同時將自身應用於其他區域,這取決於您正在使用的媒體查詢集。在那種情況下,使用 mql.matches 相反,因為您的主邏輯交換機是更好的路由,即使它意味著相同的程式碼可能會執行多次。

 示例 - 對響應式佈局做出反應

讓我們看一個更精細的例子,現在使用JavaScript來響應3列響應式佈局,其中一個CSS媒體查詢的範圍與另一個CSS媒體查詢重疊,以及如何在我們的JavaScript處理函式中處理它。當瀏覽器寬度為840px或更低時,以下3列布局使用普通CSS媒體查詢更改為2列,而當600px或更低時,更改為單列。這是我們將首先使用的示例頁面:

通過860px和600px斷點調整頁面大小,以檢視結構中的佈局偏移。現在,我們在每個列中都有靜態文字,分別顯示列的原始寬度 - “ 180px固定和 190px ”。我們將使用JavaScript在840px和600px斷點處動態更改此文字,以相應地反映列寬的變化。結果如下:

通過860px和600px斷點調整新頁面的大小,以檢視文字更新以反映當前列狀態。為此,我們的JavaScript必須對頁面CSS中使用的相同兩個媒體查詢做出反應:

  • @media(最大寬度:840px){}

  • @media(最大寬度:600px){}

並考慮以下3種情況:

  • 佈局為840px或更低時

  • 當佈局為600px時低於

  • 當佈局既不是860px或更低也不是600px或更低(無響應)

這是完整的JavaScript:

1

2

3

4

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">var leftcolumn = document.getElementById(“leftcolumn”)。getElementsByTagName(“em”)[0]</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

var rightcolumn = document.getElementById(“rightcolumn”)。getElementsByTagName(“em”)[0]</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

var maincolumn = document.getElementById(“contentcolumn”)。getElementsByTagName(“em”)[0]</font></font><font></font>

<font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

var mqls = [</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

window.matchMedia(“(max-width:840px)”),</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

window.matchMedia(“(max-width:600px)”)</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

]</font></font><font></font>

<font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

function mediaqueryresponse(mql){</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

if(mqls [0] .matches){// {max-width:840px}查詢匹配</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

leftcolumn.innerHTML =“180px”//不是多餘的</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

maincolumn.innerHTML =“流體(響應佈局觸發)”</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

rightcolumn.innerHTML =“流體(響應佈局觸發)”</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

if(mqls [1] .matches){// {max-width:600px}查詢匹配</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

leftcolumn.innerHTML =“流體(響應佈局觸發)”</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

if(!mqls [0] .matches &&!mqls [1] .matches){//兩個查詢都不匹配</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

rightcolumn.innerHTML =“190px”</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

leftcolumn.innerHTML =“180px”</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

maincolumn.innerHTML =“固定”</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font><font></font>

<font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

forvar i = 0; i <mqls.length; i ++){</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

mediaqueryresponse(mqls [i])//在執行時顯式呼叫偵聽器函式</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

mqls [i] .addListener(mediaqueryresponse)//附加偵聽器函式以偵聽狀態更改</font></font><font></font><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">

}</font></font>

我們處理函式內部的邏輯被設定,因此程式碼的每個部分彼此不相互排斥 - (max-width: 600px)例如,當查詢匹配“ ” 時,“ ”也是如此(max-width: 840px),反之亦然,所以我們不應該使用“ else”宣告跟隨每個“ if”宣告以捕捉“對立”狀態,這可能是眾多之一。相反,只需逐步執行我們的程式碼,並最終測試何時兩個查詢都不匹配,以檢測何時佈局既不是840px也不是600px寬。

現在,看看這一行:

1

<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">  leftcolumn.innerHTML =“180px”//不是多餘的</font></font>

if佈局為840px或更低時匹配的“ ”子句內部。它可能看起來多餘 - 畢竟,leftcolumn當螢幕寬度超過840px時,我們已經設定“ ”顯示“180px”,所以進入840px,為什麼重複相同的動作?原因是我們還需要考慮在相反方向發生的事件 - 即,從窄螢幕(即:640px或更小)到更寬螢幕(即:840px或更高)。在640px階段,“ leftcolumn”文字被替換為“Fluid(響應佈局觸發)”。當用戶將瀏覽器的大小調整回840px或更高時,需要程式碼撤消在640px階段完成的操作。