26

我很困惑,仍然不确定如何用恰当的语言来解释这一点。到目前为止,我已经使用 Breakpoint 并设置了我的媒体查询。使用的断点变量如下所示:

$menustatictofixed: min-width 900px;

$breakpoint-to-ems 设置为 true。我已经根据以下 jQuery 代码段的像素值来布置页面及其所有断点变量:

$('body').append('<div style="position: fixed; bottom: 0; right: 0; display: inline-block; font-weight: bold; padding: 5px 7px; border-radius: 5px 0 0 0; background: green; color: white; z-index: 9999;">Viewport width <span id="width"></span> px</div>');
var viewportWidth = $(window).width()
$('#width').text(viewportWidth);
$(window).resize(function() {
  var viewportWidth = $(window).width();
    $('#width').text(viewportWidth);
});

一切看起来都很干净。但是在过去的一两天里,我在为模式设置最后一个断点并让事情表现可预测时遇到了问题。不知何故,一开始看起来很干净和很好的事情,我现在在逻辑上高度怀疑,实际上是不合适的,而且在某种程度上是一团糟。因为如果你看一下下面的截图,窗口的宽度(在 Chrome 中)与使用 window.width 的 jQuery 片段的宽度不同。如果我将 window.width 替换为 window.innerWidth 以最终排除滚动条,也没有区别。获得正确结果的唯一方法是在等式中添加 15 个像素:

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

整个等式中唯一的问题是 window.width 是函数的错误选择,最好使用例如 document.documentElement.clientWidth 或其他东西或...?而这 15 个像素代表什么,以一种有点骇人听闻的方式解决了上述问题?最好的问候拉尔夫

4

7 回答 7

51

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

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

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
于 2013-11-20T20:05:18.803 回答
25

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

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

document.body.parentNode.clientWidth

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

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

那么解决这个问题的方法是什么?好吧,我想说解决方案是使用基于内容的媒体查询而不是基于设备的媒体查询,并且可以在您的查询中有一些回旋余地(特别是如果那个回旋余地大约15px)。如果您还没有,请阅读文章Vexing ViewportsA Pixel Identity Crisis,了解为什么15pxMQ 定义中的潜在闪光并不是世界上最糟糕的事情(可能还有更大的鱼要炒)。

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

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

于 2013-08-31T12:40:52.190 回答
5

这是因为scrollbar's

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

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

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

<div id="currentMedia"></div>

然后编写以下 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()方法不适用于windowdocument对象;对于这些,请.width()改用。

于 2013-08-31T08:35:58.300 回答
1

类似于@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 中添加更多具有其他值的规则。

于 2015-03-05T09:47:27.850 回答
0

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

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

因此,不要编写媒体查询,而是编写嵌套在类下的那些声明,例如:

html.myMobileBP { ... }

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

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

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

于 2014-07-02T08:26:28.737 回答
0

按照这个链接

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;
}
于 2015-11-17T12:42:05.610 回答
-1

使用 body 上的类来定义您是在移动设备、平板电脑还是台式机上,而不是使用像素。

对我来说它不起作用document.body.clientWidthinnerWidth。即使我的 js 代码必须执行以下语句,我的功能也会在 1023-1040px 之间崩溃:

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

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

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

我也推荐给你。

于 2017-05-19T11:46:19.517 回答