为什么window.width小于媒体查询中设置的视口宽度

我很困惑,仍然不确定如何用恰当的话来解释这一点。 到目前为止,我已经使用和设置了Breakpoint的媒体查询。 使用的断点变量看起来像例如:

$menustatictofixed: min-width 900px; 

$ breakpoint-to-ems设置为true。 我已根据以下jQuery代码段的像素值布置了包含所有Breakpoint变量的页面:

 $('body').append('
Viewport width px
'); var viewportWidth = $(window).width() $('#width').text(viewportWidth); $(window).resize(function() { var viewportWidth = $(window).width(); $('#width').text(viewportWidth); });

一切看起来都很干净。 但是在过去的一两天里,我遇到了为模式设置最后断点并让事情表现出可预测性的问题。 不知怎的,那些看起来干净整洁的东西,我现在在逻辑上非常怀疑,实际上是不合适的,不知何故是一团糟。 Cuz如果你看一下下面的截图 ,窗口的宽度(在Chrome中)与使用window.width的jQuery代码段的宽度不同。 如果我用window.innerWidth替换window.width来最终排除滚动条也没有区别。 获得正确结果的唯一方法是在等式中添加15个像素:

 var viewportWidth = $(window).width() + 15; 

整个方程中唯一的问题是window.width是错误的函数选择,最好是使用例如document.documentElement.clientWidth或其他东西或……? 对于15个像素代表什么,以一点点hacky方式解决了上面的问题? 最好的问候拉尔夫

答案是滚动条,解决方案很棘手。

媒体查询很有趣。 它们在浏览器中的行为并不完全相同,这意味着使用它们有时可能不那么容易。 例如,在OS X上的-webkit / -blink和Win8上的IE10中,滚动条覆盖在页面上。 但是,在-moz中,滚动条不会覆盖到页面上。 获取页面“可视区域”的最佳方法是使用以下的vanilla JavaScript行(假设您有一个有效的HTML文档):

 document.body.parentNode.clientWidth 

这样做是找到body元素,找到它的父元素(在有效文档中将是html元素),然后在渲染后找到它的宽度。 这将为您提供您感兴趣的宽度。 这也是一个无用的宽度

您可能会问,为什么实际的客户端宽度无用? 这不是因为它因浏览器而异,因为它确实如此。 这是因为这不是width媒体查询实际测试的内容! 什么width媒体查询测试 window.innerWidth ,这是你现在实际使用的。

那么这个问题的解决方案是什么? 好吧,我会说解决方案是使用基于内容的媒体查询而不是基于设备的媒体查询,并且在查询中有一些摆动空间(特别是如果那个摆动空间大约是15px )。 如果您还没有,请阅读文章Vexing Viewports和A Pixel Identity Crisis,以了解为什么MQ定义中潜在的15px微光不是世界上最糟糕的东西(可能有更大的鱼类可以炒) 。

因此,最后继续使用$breakpoint-to-ems: true并根据内容何时中断window.innerWidth选择媒体查询,因为它是处理跨浏览器问题的唯一理智方式。 从各种问题的粗略一瞥,似乎大多数浏览器和操作系统都转移到覆盖滚动条(从Firefox 24开始,每个OS X浏览器都会有一个,Ubuntu的Unity UI 引入它们 ),所以努力做到未来友好,我建议不要担心滚动条偏移,并且浏览器中的网站看起来略有不同。 请记住,正如Ethan Marcotte雄辩地说的那样:

网络本质上是不稳定的媒介

这对我有用 : CSS媒体查询和JavaScript窗口宽度不匹配 。

而不是使用$(window).width(); 其中包括滚动条获取内部宽度,如下所示:

 function viewport() { var e = window, a = 'inner'; if (!('innerWidth' in window )) { a = 'client'; e = document.documentElement || document.body; } return { width : e[ a+'Width' ] , height : e[ a+'Height' ] }; } var vpWidth = viewport().width; // This should match your media query 

这是因为scrollbar's

我找到的最正确的解决方案是使用媒体查询将实际窗口大小传递给Javascript。 您必须按照以下步骤操作:

  • 在页面中添加隐藏元素,
  • 使用媒体查询来更改该元素的max-width属性,
  • 通过Javascript读回该元素的max-width属性。

例如,将以下元素添加到页面:

 

然后编写以下CSS规则:

 #currentMedia { display: none; } @media (max-width: 720px) { // Make arrows in the carousel disappear... #currentMedia { max-width: 720px; } } 

然后,从Javascript方面,您可以写:

 if (parseInt(jQuery("#currentMedia").css("max-width"), 10) <= 720) { // Code HERE.. } 

无论滚动条大小如何,它都将是准确的,因为该值来自触发轮播消失的相同媒体查询。

我在所有主要的最新浏览器上测试了这个解决方案,它给出了正确的结果

您可以在quirksmode.org上找到此页面上哪些浏览器支持哪些属性的大摘要。

你最好的选择可能是抓取页面中的元素(使用document.body支持,或者document.getElementById或其他),遍历其offsetParent链以找到最顶层的元素,然后检查该元素的clientWidth和clientHeight。

innerWidth文档

.innerWidth()方法不适用于windowdocument对象; 对于这些,请改用.width()

与@ Snugugs的答案类似,但对我的用例更好:

CSS(注意我使用LESS,所以@tabletMin和@desktopMin转换为我在别处设置的断点变量:

  #cssWidth { display:none; content:'mobile'; } /* Responsive styles (Tablet) */ @media (min-width: @tabletMin) { #cssWidth { content:'tablet'; } /* Other tablet CSS... */ } /* Responsive styles (Desktop) */ @media (min-width: @desktopMin) { #cssWidth { content:'desktop'; } /* Other Desktop CSS... */ } 

然后在JS中:

  getView = function() { // If #cssWidth element does not exist, create it and prepend it do body if ($('#cssWidth').length === 0) { $('body').prepend($(document.createElement('div')).attr('id', 'cssWidth')); } // Return the value of the elements 'content' property return $('#cssWidth').css('content'); }; 

然后getView()函数将返回字符串’mobile’,’tablet’或’desktop’,具体取决于媒体查询所看到的宽度。

这可以扩展为适合更多视口宽度,只需在CSS中添加更多规则和其他值。

@Snugug的回答给出了一个非常好的解释,为什么会发生这种情况,@ TusharGupta也有一个很好的解决方案,它将mediaquery检测到的宽度引用到javascript。 下面的解决方案是通过使用javascript检测到的宽度来触发布局更改。

如果您需要使用javascript像素宽度检测同步媒体查询,解决问题的一种方法是根据您使用javascript添加的类触发css布局更改。

因此,不要编写mediaqueries,而是编写嵌套在类下的声明,例如:

 html.myMobileBP { ... } 

在你的javascript / jQuery中,添加这个类,如:

 if ($(window).width() < myMobileBPPixelSize) { $("html").addClass("myMobileBP"); } 

为了进一步推动这一点,您可能需要考虑缺少javascript支持。 定义进一步包装在html.no-js类中的html.no-js ,然后使用javascript删除.no-js类并应用上述通过javascript类添加断点的解决方案。

点击此链接

 function getWindowWidth() { var windowWidth = 0; if (typeof(window.innerWidth) == 'number') { windowWidth = window.innerWidth; } else { if (document.documentElement && document.documentElement.clientWidth) { windowWidth = document.documentElement.clientWidth; } else { if (document.body && document.body.clientWidth) { windowWidth = document.body.clientWidth; } } } return windowWidth; } 

使用body上的类来定义您是使用移动设备,平板电脑还是桌面,而不是使用像素。

对我来说,它没有工作document.body.clientWidthinnerWidth 。 即使我的js代码必须执行此语句,我的function在1023-1040px之间崩溃:

 if($(window).width()<1024) 

解决方案是将一个小于1024的新类放在体上并将其命名为“small-res”并使用它而不是我的代码而不是像素validation:

 if($(body).hasClass('small-res')) 

我也推荐给你。

Interesting Posts