issue with CSS media queries(scrollbar)
Asked Answered
G

7

27

I am having problem with css media query in Firefox. It works correct in Chrome like I made two DIVs and want a scrollbar. If I decrease the screen size of firefox upto 800px then both DIVs collapse and after some pixels media query works but that not happens in Chrome.

check this fiddle http://jsfiddle.net/RMvqC/2/

Gregale answered 16/11, 2011 at 4:46 Comment(3)
+1 i also facing the same issueBatik
I would kill for a media query like @media all and (max-width: calc(980px + scrollbar-width))Ardrey
modern solution using media queries: https://mcmap.net/q/534823/-media-queries-and-scrollbar-widthBellman
B
8

Firefox & Webkit based browsers render the scrollbar differently. In Firefox, MediaQuery considered width of scrollbar which is 15px with the screen width, but in Webkit based browsers it's not considered scrollbar with the screen width. So, that's why the floated DIVs are collapsed in Firefox.

I did some stuff with css may be that's help you. (check this fiddle)

        html {
            /* force scrollbars */
            height: 101%;
        }
        body {
            margin: 0; 
            padding:0; 
            white-space:nowrap; 
        }  
        #box1,
        #box2 {
            display:inline-block;
            width: 400px;
            height: 200px;  
            vertical-align:top;
            white-space:normal;
        }
        #box1 {
            background: #ce0000;
             margin-right:-5px;
        }
        #box2 {
            background: #8e0000;
        }

        @media screen and (max-width: 799px) { 
            body { 
                white-space:normal; 
            }
            #box1,
            #box2 {
                width: 300px;
            }
        }
Batik answered 16/11, 2011 at 7:31 Comment(5)
Such a pain, this is why I hate front end sometimes/most of the timeGermane
This has since changed around Chrome 29 I think. The scrollbar is now included in the width of the page with respect to media query calculationInhospitable
It's a shame that it's 2020 and this is still an issue. Makes media queries kind of useless for fine-tuned stuff without hacky javascript.Enclitic
It's 2021 and it looks like media queries on webkit based browsers have started to consider the width of the scrollbar. Correct me if I'm wrong.Emarginate
@Emarginate It seems that way, but not the case with Safari 14, right?Goosander
H
16

I SOLVED this issue by calling the "mqGenie" javascript in the head of my project.

Now the widths of my media queries work fine ( with the same value ) on Chrome, Safari, Firefox and IE with or without scroolbars.

This javascript Adjusts CSS media queries in browsers that include the scrollbar width in the viewport width so they fire at the intended size.

You can download it from this url:

http://stowball.github.io/mqGenie/

Haruspicy answered 28/1, 2014 at 19:28 Comment(3)
This appears to be the real solution as much as I loathe adding MORE javascript to my project to just accommodate faulty browser behavior. Atleast it's very lightweight clocking in under 1.2KB. I might actually embed this source right into my page instead.Algetic
I feel dirty for using this, but it seems to be the only way to solve my problem.Ardrey
This does exactly what media queries should already do. Thank you for solving a hugely frustrating bug.Cinematography
B
8

Firefox & Webkit based browsers render the scrollbar differently. In Firefox, MediaQuery considered width of scrollbar which is 15px with the screen width, but in Webkit based browsers it's not considered scrollbar with the screen width. So, that's why the floated DIVs are collapsed in Firefox.

I did some stuff with css may be that's help you. (check this fiddle)

        html {
            /* force scrollbars */
            height: 101%;
        }
        body {
            margin: 0; 
            padding:0; 
            white-space:nowrap; 
        }  
        #box1,
        #box2 {
            display:inline-block;
            width: 400px;
            height: 200px;  
            vertical-align:top;
            white-space:normal;
        }
        #box1 {
            background: #ce0000;
             margin-right:-5px;
        }
        #box2 {
            background: #8e0000;
        }

        @media screen and (max-width: 799px) { 
            body { 
                white-space:normal; 
            }
            #box1,
            #box2 {
                width: 300px;
            }
        }
Batik answered 16/11, 2011 at 7:31 Comment(5)
Such a pain, this is why I hate front end sometimes/most of the timeGermane
This has since changed around Chrome 29 I think. The scrollbar is now included in the width of the page with respect to media query calculationInhospitable
It's a shame that it's 2020 and this is still an issue. Makes media queries kind of useless for fine-tuned stuff without hacky javascript.Enclitic
It's 2021 and it looks like media queries on webkit based browsers have started to consider the width of the scrollbar. Correct me if I'm wrong.Emarginate
@Emarginate It seems that way, but not the case with Safari 14, right?Goosander
I
7

Firefox & Opera follows W3C spec which is to include scrollbar width in media queries width (the reason might be to avoid infinite loop as described in a comment here), while Webkit does not (possibly coz they think it makes no sense)

There is a workaround (I've only tested this on FF), apparently if you force scrollbar to be visible all the time, then the width will now be consistent with Webkit. Here's the code:

html
{
   overflow:hidden;
   height:100%;
}
body
{
   position:relative;
   overflow-y:scroll;
   height:100%;
   -webkit-overflow-scrolling:touch; /* So iOS Safari gets the inertia & rubber-band effect */
}

If you want to apply this to FF & Opera only, you can resort to CSS hacks:

/* Firefox */
@-moz-document url-prefix()
{
    html
    {
        overflow:hidden;
        height:100%;
    }
    body
    {
        position:relative;
        overflow-y:scroll;
        height:100%;
        /*-webkit-overflow-scrolling:touch;*/
    }
}

/* Opera */
x:-o-prefocus, html
{
    overflow:hidden;
    height:100%;
}
x:-o-prefocus, body
{
    position:relative;
    overflow-y:scroll;
    height:100%;
}

It goes without saying, the caveat is the scrollbar will be visible at all times, which might be an okay compromise.

Inaction answered 13/12, 2012 at 23:6 Comment(0)
T
1

This is peripherally related, but I found a way to detect which media-query the browser is actually using at any given moment, without having to muck around with scrollbar and body widths...

Basically, define a an absolutely positioned 1-x-1-pixel-sized list somewhere in your body, with a list-item for each media-query condition you want to be "watchable".

Then in each media-query definition, show/hide the corresponding list-item, and then simply check whether that item is visible from within your script.

Example:

<body>
    ...
    <ul id="mediaQueryHelper">
        <li id="desktop"></li>
    </ul>
</body>

<style type="text/less">
    #mediaQueryHelper {
        position: absolute;
        height: 1px;
        width: 1px;
        visibility: hidden;
        top: -999px;
        left: -999px;
    }

    @media screen and (min-width: 481px)
    {
       #desktop { display: inline; }
    }

    @media screen and (min-width: 320px) and (max-width: 480px)
    {
       #desktop{ display: none; }
    }

</style>

<script type="text/javascript">
    $(document).ready(function()
    {
        var _desktop = $("#desktop");

        $(window).resize(function() {
            console.log("media-query mode: " + _desktop.is(":visible") ? "DESKTOP" : "MOBILE");
        });
    });
</script>
Tetroxide answered 31/1, 2014 at 22:18 Comment(0)
E
1

Play safe!

My final strategy is added 20px to the media queries and that is my default white space on the layout.

With one exception: @media (min-width: 320px) At that size a don't leave the 20px white space and include one more rule to solve minor background issues:

html body {
    min-width: 320px;
   }

20px is the scroll bar default width size.

FYI: https://www.sitepoint.com/rwd-scrollbars-is-chrome-better/

Evered answered 29/10, 2018 at 19:29 Comment(0)
T
0

You can implement a solution for Firefox pretty easily by using a CSS-hack. After wrapping your content in an extra <div> add this lines to your CSS:

/* Firefox-Hack */
body,  x:-moz-any-link {
    overflow-x: hidden;
}
#wrapper,  x:-moz-any-link {
    margin: 0 -7.5px;
}

Check the jsbin (jsfiddle is down right now)

To have richer responsive experience you could add another media query: another jsbin

The CSS-hack was found at paulirish.com

Tishtisha answered 8/11, 2012 at 11:0 Comment(0)
M
0

Short Answer

If you do not want to display the scrollbar all the time, wrap your content into <div> elements etc. you can use JavaScript to add a certain value to all media queries when the scrollbar is shown.

// check whether scrollbar is visible
var isScrollbarVisible = window.innerWidth > document.documentElement.clientWidth;

// search for media rule
var mediaRule = document.styleSheets[i].cssRules[j];

// update media rule
mediaRule.media.mediaText = '..'


Long Answer

I wrote a small script which you can include on your page. It detects when the window is resized and changes all media queries if needed. The value of the css variable --replace-media-scrollbar is used as the width of the scrollbar or 15px if no value was found. This works for the media queries with, min-width, max-width, height, min-height and max-height even when they are connected using and.

JavaScript:

function* visitCssRule(cssRule) {
    // visit imported stylesheet
    if (cssRule.type == cssRule.IMPORT_RULE)
        yield* visitStyleSheet(cssRule.styleSheet);

    // yield media rule
    if (cssRule.type == cssRule.MEDIA_RULE)
        yield cssRule;
}

function* visitStyleSheet(styleSheet) {
    try {
        // visit every rule in the stylesheet
        var cssRules = styleSheet.cssRules;
        for (var i = 0, cssRule; cssRule = cssRules[i]; i++)
            yield* visitCssRule(cssRule);
    } catch (ignored) {}
}

function* findAllMediaRules() {
    // visit all stylesheets
    var styleSheets = document.styleSheets;
    for (var i = 0, styleSheet; styleSheet = styleSheets[i]; i++)
        yield* visitStyleSheet(styleSheet);
}

// collect all media rules
const mediaRules = Array.from(findAllMediaRules());

// read scrollbar width
var style = getComputedStyle(document.documentElement);
var scrollbar = style.getPropertyValue('--replace-media-scrollbar') || '15px';

// update media rules
if (scrollbar != '0px') {
    var oldValue = '0px';
    function updateMediaRulesScrollbar() {
        var newValue = window.innerWidth > document.documentElement.clientWidth ? scrollbar : '0px';
        // if value changed
        if (oldValue != newValue) {
            for (var i = 0, mediaRule; mediaRule = mediaRules[i]; i++) {
                var regex = RegExp('\\((width|min-width|max-width|height|min-height|max-height): (calc\\([^)]*\\)|[^)]*)\\)', 'g');
                var replacement = '($1: calc($2 - ' + oldValue + ' + ' + newValue + '))';
                mediaRule.media.mediaText = mediaRule.media.mediaText.replace(regex, replacement);
                console.log(mediaRule);
            }
        }
        oldValue = newValue;
    }
    updateMediaRulesScrollbar();
    window.onresize = updateMediaRulesScrollbar;
}

Optional CSS:

:root {
  --replace-media-scrollbar: 15px;
}
Modify answered 10/5, 2020 at 16:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.