如何使用jQuery $(window).innerWidth()来实现CSS媒体查询?

18

我正在尝试让 jQuery 管理菜单,而当调整浏览器大小时,CSS 对窗口背景进行一些处理。

因此 jQuery 会做类似这样的事情:

if ( $(window).innerWidth() < mediaQueries['small']) {
    // (where 'small' would be 966)
    // Perform jQuery stuff on a menu ul
}

而 CSS 也有这样的语法:

@media all and (max-width: 966px) {
    body {
        background: url(smallback.jpg) no-repeat 0 0;
    }
}

在使用Firefox时,有一个17像素的间隙(似乎是垂直滚动条的宽度),其中jQuery已经处理,但CSS未处理。

由于其他浏览器可能会为其滚动条使用不同的宽度,因此仅将17px添加到CSS中并不能真正解决问题。那么如何让jQuery考虑滚动条呢?$(window).innerWidth()对我来说似乎做不到这一点。

任何帮助将大大受到赞赏。

在Firefox、Opera或IE中打开此页面以获取问题的独立版本。(Chrome和Safari没有此问题。截至目前为止:Webkit:+1,Gecko:-1,Trident:-1,Presto:-1。)


如果你使用 width() 会发生什么? - Ben
@Ben,这没关系。看起来JavaScript忘记了滚动条? - Simon
你能否在某个地方设置一个基本示例供人们测试? - Ben
5个回答

35
除了JackieChiles提供的解决方案外:
使用
var width = Math.max( $(window).width(), window.innerWidth);
将始终在任何浏览器中获取没有滚动条的宽度。
这个解决方案(依我之见)更好,因为JS不依赖于任何CSS。
感谢JackieChiles和Arjen提供的解决方案!

1
谢谢,这个解决方案对我很有用。jQuery文档 .innerWidth() 不适用于 window 和 document 对象;对于这些对象,请改用 .width()。我已经相应地编辑了你的答案。 - Andrey Mikhaylov - lolmaus
2
我的问题在Webkit浏览器中没有可爱的显示。我不得不使用以下方式进行修复:isWebKit ? $(window).width() : Math.max($(window).width(), window.innerWidth); - Vahid Hallaji

10

我解决在媒体查询确切时间触发JavaScript的方法(即使面对设备或浏览器的奇怪行为,如此处所见)是响应媒体查询所做的更改来触发window.resize逻辑。以下是一个示例:

CSS

    #my-div
    {
        width: 100px;
    }

    @media all and (max-width: 966px)
    {
        #my-div
        {
            width: 255px;
        }
    }

JavaScript

    var myDivWidth;

    $(document).ready(function() {
        myDivWidth = $('#myDiv').width();

        $(window).resize(function () {
            if ($('#myDiv').width() != myDivWidth) {
                //If the media query has been triggered
                myDivWidth = $('#myDiv').width();
                //Your resize logic here (the jQuery menu stuff in your case)
            }
        });
    });

在这个例子中,每当 #myDiv 改变大小(当媒体查询被触发时会发生),你的 jQuery 调整逻辑也将运行。

为了简单起见,我使用了一个元素宽度,但你可以轻松地使用你正在改变的任何属性,比如 body 背景。

这种方法的另一个优点是,它尽可能地保持 window.resize 函数的轻量级,这总是很好的,因为它在大多数现代浏览器中每次窗口大小改变一个像素时都会被调用。

你遇到的 bug 在我看来似乎是一个特定于浏览器的问题,正如你所说。虽然它在直觉上似乎不正确,但 Firefox(和其他出现这个问题的浏览器)实际上似乎更接近于W3C 媒体查询推荐标准。该推荐标准指出,视口宽度包括滚动条,而 JavaScript 窗口宽度似乎不包括滚动条,因此存在差异。


非常感谢!虽然这只是一个解决方法,但它确实是有帮助的建议,因为现在用户将不会感受到任何差异。 - Simon
1
@Simon 你应该将Jackie的答案标记为正确答案(在其旁边打勾)。 - Ben
2
@Simon:仅使用window.innerWidth将为您提供包括滚动条在内的完整宽度,而不是jQuery $(window).innerWidth()。虽然window.innerWidth可能会解决您在Firefox中遇到的问题,但它将在WebKit浏览器中出现问题。 - Drew Gaynor
1
@JackieChiles 哦,不错!忘记了JS != JQ。:-)虽然我总是讨厌“if (IE) then ... if (FF) then ... if (Chrome) then ...”这样的代码,但我想在我们摆脱它之前可能需要一段时间(如果有的话)。 - Simon
此外,您可能希望为 $(window).resize(function() {}); 添加超时,以便调整窗口大小不会因每个像素的重新调整而变慢。使用50毫秒的超时应该足够了。 - Simon
显示剩余2条评论

4

如果你正在使用Modernizr,你可以包含媒体查询polyfill,它简化了媒体查询检查:

if (Modernizr.mq('all and (max-width: 966px)')) {
    ...
}

这与您的CSS方便地完全相同:

@media all and (max-width: 966px) {
    ...
}

如果您无法使用Modernizr的polyfill,请继续检查Math.max(document.width, window.innerWidth)

2

-1
var viewport = jQuery(window).innerWidth();

if( viewport > 979 )
{
  // your code here
}

很抱歉,但那根本不是问题的答案。我认为你帮助别人解决问题很好,但如果你不读懂他们的问题,就不会有所帮助。 - Simon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接