Why is the window.width smaller than the viewport width set in media queries

后端 未结 7 1990
轻奢々
轻奢々 2020-12-01 09:45

I am quite puzzled and still unsure how to explain this in proper words. So far i\'ve used and set up my media queries with Breakpoint. An used Breakpoint-variable looks lik

相关标签:
7条回答
  • 2020-12-01 10:02

    The answer is scrollbars, and the solution is tricky.

    Media queries are interesting. They don't behave precisely the same across browser, meaning using them can sometimes not be so easy. In -webkit/-blink on OS X and IE10 on Win8 for example, scrollbars are overlaid onto the page. In -moz, however, scrollbars are not overlaid onto the page. The best way to get the "viewable area" of the page is the following line of vanilla JavaScript (assuming you have a valid HTML document):

    document.body.parentNode.clientWidth
    

    What this will do is find the body element, find it's parent (which in a valid document will be the html element), and then find it's width after rendering. This will give you the width you're interested in seeing. It's also a useless width to have.

    Why, you may ask, is having the actual client width useless? It's not because it varies from browser to browser, because it does. It's because that's not what the width media queries are actually testing! What width media queries test is window.innerWidth, which is what you're in essence using now.

    So what is the solution to this problem? Well I'd say the solution is to use content based media queries instead of device based media queries and be OK with some wiggle room in your queries (especially if that wiggle room is approx. 15px). If you haven't already, read the articles Vexing Viewports and A Pixel Identity Crisis to get an idea as to why a potential 15px shimmer in your MQ definitions isn't the worst thing in the world (there are probably bigger fish to fry).

    So, in conclusion continue using $breakpoint-to-ems: true and choose your media queries based on when content breaks to window.innerWidth as it's the only sane way of handling cross-browser issues. From a cursory glance of various issues, it appears as if most browsers and OSes are moving to an overlay scrollbar (as of Firefox 24 every OS X browser will have one, Ubuntu's Unity UI introduced them), so in an effort to be future friendly, I'd suggest not worrying about the scroll bar offset and be OK with sites looking slightly different across browser. Remember, as Ethan Marcotte so eloquently put:

    The Web is an Inherently Unstable Medium

    0 讨论(0)
  • 2020-12-01 10:02

    @Snugug 's answer gives a really good explanation as to why this is happening, and @TusharGupta has a good solution as well that references the mediaquery detected width to javascript. Below solution goes the other way around by using javascript detected width to trigger layout changes.

    In case you need to sync mediaqueries with your javascript pixel width detection, one way of approaching the problem is to trigger css layout changes based on classes you add with javascript.

    So, instead of writing mediaqueries, write those declarations nested under a class, say:

    html.myMobileBP { ... }
    

    And in your javascript/jQuery, add this class like:

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

    To drive this even further, you might want to consider lack of javascript support. Define mediaqueries that are furthermore wrapped in a html.no-js class, then with javascript remove the .no-js class and apply the above solution of adding breakpoints via javascript classes.

    0 讨论(0)
  • 2020-12-01 10:07

    Use classes on body to define if you are on mobile, tablet or desktop instead using pixels.

    For me it did not work document.body.clientWidth or innerWidth. My functionality crashes between 1023-1040px even if my js code must do this statement:

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

    The solution was to put on body a new class for less than 1024 and name it "small-res" and use it than in my code instead of pixels verification:

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

    I recommend it to you too.

    0 讨论(0)
  • 2020-12-01 10:08

    IT's because of the scrollbar's

    The most correct solution I found is to use media queries to pass the actual window size to Javascript. You have to follow these steps:

    • Add a hidden element to your page,
    • Use media queries to alter the max-width property of that element,
    • Read back the max-width property of that element through Javascript.

    For instance, add the following element to your page:

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

    Then write the following CSS rules:

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

    Then, from the Javascript side, you can write:

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

    And it will be accurate regardless of the scrollbar size, since the value comes from the same media query that triggers the carousel's disappearance.

    I tested this solution on all major recent browsers, and it gives correct results.

    You will find the big summary of what properties are supported on what browsers on this page on quirksmode.org.

    Your best bet is probably to grab an element in the page (using document.body where supported, or document.getElementById or whatever), walk its offsetParent chain to find the topmost element, then examine that element's clientWidth and clientHeight.

    innerWidth documentation

    .innerWidth() method is not applicable to window and document objects; for these, use .width() instead.

    0 讨论(0)
  • 2020-12-01 10:09

    follow this link

    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;
    }
    
    0 讨论(0)
  • 2020-12-01 10:11

    This is what worked for me: CSS media queries and JavaScript window width do not match.

    Instead of using $(window).width(); which includes scrollbars get the inner width like this:

    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
    
    0 讨论(0)
提交回复
热议问题