Search code examples
htmlcssgoogle-chromescrollbarmedia-queries

Media query layout issue with scroll bar in chrome


I'm getting this strange issue with media queries in Chrome that is fairly obscure but is really bugging me so I'm hoping to either find a solution on here or at the least confirm that I'm not going mad...

Basically, it seems that when a media query kicks in that will take the page from a state where the content is scrolling off of the screen (so you have the y-axis scroll bar) to a state where the content now fits on the screen (so the y-axis scroll bar should not appear) there seems to be a small period whereby the page layout is rendered as if the scroll bar is there even when it is not (so something that is trying to fill the whole screen will appear not to for this period)

I have set up a simple page to showcase the issue. It contains two floating divs that when a media query kicks in at less than 500px wide are set to no longer float and have a greater width - at which point the header bar changes from blue to red too (for clarity).

http://appasylum.net/test/mediaQueryChromeScrollBarIssue/

  <!DOCTYPE html>
  <html>
  <head>

      <title>Media Query Chrome Scrollbar issue</title> 
      <style type="text/css">

      html,
      body 
      {
         margin:0;
         padding:0;
      }

      .header
      {
        background-color: blue;
        padding: 10px;
        color: white;
        font-family: Helvetica, Arial, sans-serif;
      }

      .content
      {                
        background-color: #f5f5f5;
        border: 1px solid #e3e3e3;              
        float: left;
        width: 40%; 
        margin: 20px; 
      }

      @media (max-width: 500px) {

        .header
        {
          background-color: red;
        }

          .content
          {
            float:none;
            width: 90%;
          }
      }
      </style>

  </head>

  <body>

  <div class="header">
    Header
  </div>

  <div class="content"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. In nec purus ut quam vestibulum porta sed ultrices velit. Suspendisse dapibus justo id ligula iaculis cursus. Fusce non diam ut ante porta lacinia id vel nisl. Mauris laoreet orci vel nulla imperdiet ac rhoncus diam accumsan. Quisque sed mauris mi, sollicitudin commodo ligula. Etiam arcu arcu, vehicula ut porttitor id, viverra non augue. Mauris laoreet fringilla tempus. Praesent elit elit, molestie eget bibendum vitae, fringilla nec turpis. Suspendisse eget ipsum sed sem egestas ultricies. Cras eleifend imperdiet magna nec elementum. Etiam arcu arcu, vehicula ut porttitor id, viverra non augue. Mauris laoreet fringilla tempus. Praesent elit elit, molestie eget bibendum vitae, fringilla nec turpis. Suspendisse eget ipsum sed sem egestas ultricies. Cras eleifend imperdiet magna nec elementum.Etiam arcu arcu, vehicula ut porttitor id, viverra non augue. Mauris laoreet fringilla tempus. Praesent elit elit, molestie eget bibendum vitae, fringilla nec turpis. Suspendisse eget ipsum sed sem egestas ultricies. Cras eleifend imperdiet magna nec elementum.
  </div>

  <div class="content"> Aliquam in mauris quis arcu aliquam aliquam eu ut mauris. Quisque ut tortor eu massa scelerisque vehicula. Morbi velit diam, egestas at placerat vel, tincidunt a nulla. Vivamus arcu augue, vulputate at elementum sit amet, adipiscing quis odio. Etiam arcu arcu, vehicula ut porttitor id, viverra non augue. Mauris laoreet fringilla tempus. Praesent elit elit, molestie eget bibendum vitae, fringilla nec turpis. Suspendisse eget ipsum sed sem egestas ultricies. Cras eleifend imperdiet magna nec elementum
  </div>

  </body>
  </html>

To replicate open the above link in a window greater than 500px wide (blue header), and at a height that only just lets the content scroll off the page - then slowly reduce the width of the window until it goes red (ie is less than 500px in width). Assuming the height of your window results in the un-floated divs no longer needing a scroll bar (or vice versa) - at the point of transition between red and blue headings (ie media query becoming being active) you should notice for a very short period that the red header does not fill the entire viewport width.


Solution

  • I think Chrome enters into infinite loop here. After you go just a tad below 500px he removes vertical scrollbar, but right after he removes scrollbar window width is back above 500px and he applies CSS for that width which in turn again needs vertical scrollbar and we are again at the same place where we started... so infinite loop. Basically Chrome just protects itself from infinite loop by leaving the space that the vertical scrollbar was using.

    As far as I can see you can either remove the scrollbar completely i.e. overflow:hidden on body (but I guess that's not much help for 99% of websites), or leave it on at all times on body with overflow-y:scroll.

    EDIT: Maybe you could try removing scrollbar on body tag, but encapsulate all content in one div with overflow-y:scroll. Even though div is as wide as body, it seems to work this way, no glitches in my test. This would require setting up this div to be 100% height of the screen which could be though.