$(window).width()与媒体查询不同


186

我在一个项目上使用Twitter Bootstrap。除了默认的引导样式之外,我还添加了一些自己的样式

//My styles
@media (max-width: 767px)
{
    //CSS here
}

当视口的宽度小于767px时,我还使用jQuery更改页面上某些元素的顺序。

$(document).load($(window).bind("resize", checkPosition));

function checkPosition()
{
    if($(window).width() < 767)
    {
        $("#body-container .main-content").remove().insertBefore($("#body-container .left-sidebar"));
    } else {
        $("#body-container .main-content").remove().insertAfter($("#body-container .left-sidebar"));
    }
}

我遇到的问题是,$(window).width()由CSS计算的宽度与由CSS计算的宽度似乎并不相同。当$(window).width()返回767时,css将其视口宽度计算为751,因此似乎存在16px的差异。

有谁知道是什么原因造成的,以及如何解决这个问题?人们建议不要考虑滚动条的宽度,而应该使用滚动条的宽度$(window).innerWidth() < 751。但是,理想情况下,我想找到一种解决方案,该解决方案可以计算滚动条的宽度,并且与我的媒体查询一致(例如,两种情况都对照值767进行检查)。因为肯定不是所有浏览器的滚动条宽度都为16px?


1
如果($('html')。width()<= 767){//做某事}
Vaibs_Cool 2013年

@Vaibs_Cool感谢您的建议,但我仍然得到相同的结果
Pattle


:这里回答我[此处输入链接的描述] [1] [1] stackoverflow.com/questions/11309859/...
Rantiev

您是否希望“ document.documentElement.clientWidth”(而不是“ $(window).width()”)工作?编辑:我的错误,只是看到了Vaibs_Cool的答案。
joshhunt 2014年

Answers:


293

如果不必支持IE9,则可以使用window.matchMedia()MDN文档)。

function checkPosition() {
    if (window.matchMedia('(max-width: 767px)').matches) {
        //...
    } else {
        //...
    }
}

window.matchMedia与CSS媒体查询完全一致,并且浏览器支持也很好:http : //caniuse.com/#feat=matchmedia

更新:

如果必须支持更多浏览器,则可以使用Modernizr的mq方法,它支持所有了解CSS中媒体查询的浏览器。

if (Modernizr.mq('(max-width: 767px)')) {
    //...
} else {
    //...
}

8
如果您有能力使用Modernizr库,那么这是最好的答案。
richsinn 2014年

1
此解决方案更好:stackoverflow.com/a/19292035/1136132(第二代码)。只有JS。
joseantgv

@joseantgv我的解决方案也是仅js。您能解释一下为什么您链接的解决方案更好吗?
ausi 2015年

2
@edwardm Modernizr.mq仅返回一个布尔值,因此您必须在onresize事件处理程序中自行调用它。
ausi

2
@Bernig window.matchMedia是推荐的方式,因为它不会触发回流,这取决于如何往往你调用函数这可能会导致性能问题。如果您不想直接使用Modernizr,则可以从src / mq.jssrc / injectElementWithStyles.js复制源代码。
ausi

175

检查更改媒体查询的CSS规则。这样可以保证始终有效。

http://www.fourfront.us/blog/jquery-window-width-and-media-queries

HTML:

<body>
    ...
    <div id="mobile-indicator"></div>
</body>

Javascript:

function isMobileWidth() {
    return $('#mobile-indicator').is(':visible');
}

CSS:

#mobile-indicator {
    display: none;
}

@media (max-width: 767px) {
    #mobile-indicator {
        display: block;
    }
}

9
这是比其他答案中提到的JS hacks更优雅的解决方案。
勒内·罗斯

3
+1这很聪明。我喜欢如果要更改断点,只需更改css而不是javascript。
JoeMoe1984

这种解决方案效果很好,我发现它比投票最多的答案中提出的javascript hack更优雅。
安德烈斯·梅萨- Escallón

2
如果你使用的引导,你可以不用像CSS<div id="xs-indicator" class="xs-visible">
迷彩

33

可能是由于scrollbar,使用innerWidth而不是width喜欢

if($(window).innerWidth() <= 751) {
   $("#body-container .main-content").remove()
                                .insertBefore($("#body-container .left-sidebar"));
} else {
   $("#body-container .main-content").remove()
                                .insertAfter($("#body-container .left-sidebar"));
}

你也可以得到viewport

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' ] };
}

以上代码源码


谢谢。这将起作用,但是无论如何我都可以使用jquery来包含滚动条的宽度。我只是在想滚动条的宽度可以在不同的浏览器上改变?
Pattle

1
是使用innerWidth()或者你可以使用它像$('body').innerWidth();请参阅本stackoverflow.com/questions/8339377/...
罗汉库马尔

3
您的意思是window.innerWidth,不是在jQuery $(window)对象上,$(window).width()错误地将其返回
EJanuszewski

1
window.innerWidth如果在OSX系统偏好设置中启用了滚动条,则与Safari 8中的CSS媒体查询不一致。
奥西

10

是的,这是由于滚动条。正确答案来源:在此处输入链接描述

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' ] };
}

4

最好不要在JS范围内更改文档的宽度,而应使用CSS @media查询进行某种更改。使用此方法,可以确保JQuery函数和CSS更改同时发生。

CSS:

#isthin {
    display: inline-block;
    content: '';
    width: 1px;
    height: 1px;
    overflow: hidden;
}

@media only screen and (max-width: 990px) {
    #isthin {
        display: none;
    }
}

jQuery的:

$(window).ready(function(){
    isntMobile = $('#isthin').is(":visible");
    ...
});

$(window).resize(function(){
    isntMobile = $('#isthin').is(":visible");
    ...
});

3

我最近也遇到了同样的问题-Bootstrap 3也是如此。

$ .width()和$ .innerWidth()都不适合您。

我想到的最好的解决方案-特别是针对BS3量身定制-
检查.container元素的宽度。

您可能知道该.container元素的工作原理,
它是唯一可以为您提供BS css规则设置的当前宽度的元素。

所以它像

bsContainerWidth = $("body").find('.container').width()
if (bsContainerWidth <= 768)
    console.log("mobile");
else if (bsContainerWidth <= 950)
    console.log("small");
else if (bsContainerWidth <= 1170)
    console.log("medium");
else
    console.log("large");


3

这是前面提到的方法的替代方法,该方法依赖于通过CSS进行更改并通过Javascript进行读取。此方法不需要window.matchMedia或Modernizr。它还不需要额外的HTML元素。它通过使用HTML伪元素来“存储”断点信息来工作:

body:after {
  visibility: hidden;
  height: 0;
  font-size: 0;
}

@media (min-width: 20em) {
  body:after {
    content: "mobile";
  }
}

@media (min-width: 48em) {
  body:after {
    content: "tablet";
  }
}

@media (min-width: 64em) {
  body:after {
    content: "desktop";
  }
}

以我body为例,您可以使用任何HTML元素。您可以将所需的任何字符串或数字添加到content伪元素的中。不必一定要“移动”,依此类推。

现在,我们可以通过以下方式从Javascript中读取此信息:

var breakpoint = window.getComputedStyle(document.querySelector('body'), ':after').getPropertyValue('content').replace(/"/g,'');

if (breakpoint === 'mobile') {
    doSomething();
}

这样,我们始终可以确保断点信息是正确的,因为断点信息直接来自CSS,而我们不必为通过Javascript获得正确的屏幕宽度而烦恼。


您无需使用querySelector()getPropertyValue()。您也可以在正则表达式中查找单引号(因为不一致)。这:window.getComputedStyle(document.body, ':after').content.replace(/"|'/g, '')。而且,要使其便宜一点,您可以将其包装在下划线/短划线中._debounce(),等待约100毫秒。最后,将属性附加到<html>使输出可用于其他内容,例如工具提示禁用子句,用于在vars外查找原始标志/数据。示例:gist.github.com/dhaupin/f01cd87873092f4fe2fb8d802f9514b1
dhaupin

2

Javascript提供了多种检查视口宽度的方法。如您所见,innerWidth不包括工具栏宽度,并且工具栏宽度在系统之间会有所不同。还有一个externalWidth选项,其中包括工具栏的宽度。在Mozilla的JavaScript API第状态:

Window.outerWidth获取浏览器窗口外部的宽度。它代表整个浏览器窗口的宽度,包括侧栏(如果已展开),窗口镶边和窗口调整大小的边框/句柄。

javascript的状态使得每个平台上的每个浏览器都不能依赖于externalWidth的特定含义。

outerWidth不能很好地支持在旧的移动浏览器尽管它在主要的台式机浏览器和大多数较新的智能手机浏览器中均受支持,但。

正如ausi指出的那样,matchMedia这是一个很好的选择,因为CSS的标准化程度更高(matchMedia使用JS读取CSS检测到的视口值)。但是,即使采用了公认的标准,仍然存在忽略它们的弱智浏览器(在这种情况下,IE <10,这使得matchMedia至少在XP死之前不是很有用)。

总之,如果你只为桌面浏览器和新的移动浏览器开发,outerWidth应该给你你在找什么,有一些注意事项


1

这是处理媒体查询的一种较少涉及的技巧。跨浏览器支持有点限制,因为它不支持移动IE。

     if (window.matchMedia('(max-width: 694px)').matches)
    {
        //do desired changes
    }

有关更多详细信息,请参见Mozilla文档


1

试试这个

getData(){
    if(window.innerWidth <= 768) {
      alert('mobile view')
      return;
    }

   //else function will work

    let body= {
      "key" : 'keyValue'
    }
    this.dataService.getData(body).subscribe(
      (data: any) => {
        this.myData = data
      }
    )
}

0

始终有效并与CSS媒体查询同步的解​​决方法。

向主体添加div

<body>
    ...
    <div class='check-media'></div>
    ...
</body>

通过输入特定的媒体查询来添加样式并进行更改

.check-media{
    display:none;
    width:0;
}
@media screen and (max-width: 768px) {
    .check-media{
         width:768px;
    }
    ...
}

然后在JS中检查您要更改的样式,方法是进入媒体查询

if($('.check-media').width() == 768){
    console.log('You are in (max-width: 768px)');
}else{
    console.log('You are out of (max-width: 768px)');
}

因此,通常您可以通过输入特定的媒体查询来检查正在更改的任何样式。


0

最好的跨浏览器解决方案是使用Modernizr.mq

链接: https //modernizr.com/docs/#mq

Modernizr.mq允许您以编程方式检查当前浏览器窗口状态是否与媒体查询匹配。

var query = Modernizr.mq('(min-width: 900px)');
if (query) {
   // the browser window is larger than 900px
}

注意浏览器不支持媒体查询(例如,旧的IE),mq将始终返回false。


0
if(window.matchMedia('(max-width: 768px)').matches)
    {
        $(".article-item").text(function(i, text) {

            if (text.length >= 150) {
                text = text.substring(0, 250);
                var lastIndex = text.lastIndexOf(" ");     
                text = text.substring(0, lastIndex) + '...'; 
            }

            $(this).text(text);

        });

    }

0

我做的事 ;

<body>
<script>
function getWidth(){
return Math.max(document.body.scrollWidth,
document.documentElement.scrollWidth,
document.body.offsetWidth,
document.documentElement.offsetWidth,
document.documentElement.clientWidth);
}
var aWidth=getWidth();
</script>
...

然后在任何地方调用aWidth变量。

您需要将getWidth()放在文档主体中,以确保计算滚动条的宽度,否则从getWidth()中减去浏览器的滚动条的宽度。


-1

实现光滑的滑块,并根据分辨率在块中显示不同数量的幻灯片(jQuery)

   if(window.matchMedia('(max-width: 768px)').matches) {
      $('.view-id-hot_products .view-content').slick({
        infinite: true,
        slidesToShow: 3,
        slidesToScroll: 3,
        dots: true,
      });
    }

    if(window.matchMedia('(max-width: 1024px)').matches) {
      $('.view-id-hot_products .view-content').slick({
        infinite: true,
        slidesToShow: 4,
        slidesToScroll: 4,
        dots: true,
      });
    }

-2

试试这个

if (document.documentElement.clientWidth < 767) {
   // scripts
}

有关更多参考,请单击此处


谢谢,尽管如此,结果还是一样
Pattle
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.