使用window.matchMedia()匹配多个CSS媒体查询

一个常见的问题是如何使用它window.matchMedia() 来对多个CSS媒体查询做出反应。在JavaScript中的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或更低时,更改为单列。这是我们将首先使用的示例页面:

3列响应式布局

通过860px和600px断点调整页面大小,以查看结构中的布局偏移。现在,我们在每个列中都有静态文本,分别显示列的原始宽度 - “ 180px固定和 190px ”。我们将使用JavaScript在840px和600px断点处动态更改此文本,以相应地反映列宽的变化。结果如下:

3列响应式布局(带动态文本)

通过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阶段完成的操作。


猜你喜欢

转载自blog.51cto.com/13959020/2178432
今日推荐