187

I have a website here.

Viewed in a desktop browser, the black menu bar properly extends only to edge of the window, since the body has overflow-x:hidden.

In any mobile browser, whether Android or iOS, the black menu bar displays its full width, which brings whitespace on the right of the page. As far as I can tell, this whitespace isn't even a part of the html or body tags.

Even if I set the viewport to a specific width in the <head>:

<meta name="viewport" content="width=1100, initial-scale=1">

The site expands to the 1100px but still has the whitespace beyond the 1100.

What am I missing? How do I keep the viewport to 1100 and cut off the overflow?

Sergey Glotov
  • 20,200
  • 11
  • 84
  • 98
Indigenuity
  • 9,332
  • 6
  • 39
  • 68

22 Answers22

358

Creating a site wrapper div inside the <body> and applying the overflow-x:hidden to the wrapper instead of the <body> or <html> fixed the issue.

It appears that browsers that parse the <meta name="viewport"> tag simply ignore overflow attributes on the html and body tags.

Note: You may also need to add position: relative to the wrapper div.

Chuck Le Butt
  • 47,570
  • 62
  • 203
  • 289
Indigenuity
  • 9,332
  • 6
  • 39
  • 68
  • 52
    I found that in addition to setting the `overflow` to `hidden`, I had to set the `position` to `fixed`... – Victor S Feb 22 '13 at 05:22
  • For me, just adding `overflow-x: hidden` to the first `div` inside `body` worked just fine. No need to add another `div`, just try to set it to your outermost `div`. – Gchtr Aug 12 '13 at 15:41
  • 21
    Adding position to fixed stops me from being able to scroll! – theorise Oct 25 '13 at 15:44
  • 2
    Adding a wrapper div with overflow: hidden did the trick for me in iOS7! – Jason Farnsworth Mar 03 '14 at 07:52
  • 6
    I tried, I put all my code inside a div and give it overflow-x:hidden but doens't work, I add too but nothing changed :/ any ideas? –  Oct 25 '14 at 19:20
  • 1
    Making a div wrapper around everything in works. – Vennsoh Jun 02 '15 at 23:26
  • 2
    Wasn't working for me on MobileSafari (iOS9) until I ensured the viewport meta tag looked like this: `` - at issue here: changing the main content container can cause a big change in document height, which in turn can cause weird zooming behavior. – leepowers Nov 18 '15 at 03:42
  • 4
    @leepowers `overflow-x: hidden` is still not working for me even after I add this meta tag. Could you please share a link to your website where it is working? – jupiteror Dec 01 '15 at 11:29
  • overflow: hidden; height: 100%; together works for me – craigstar Apr 15 '16 at 18:47
  • 1
    Definitely ^ if you find an element outside of that region make sure it's not set to absolute but instead set to fixed. – JoeCodeCreations Apr 19 '17 at 09:54
  • @theorise nothing worked but the `position: fixed`. thank you <33 – oldboy May 20 '17 at 01:10
  • 12
    Hey gang, when I found that `position:relative` works as well. – Thomas Valadez Apr 11 '18 at 16:43
  • `overflow: scroll` if you want the user to still be able to see the overflowed content – user3666653 Nov 04 '19 at 20:15
  • I have tried this for my ionic app (only for iOs Devices) but it's not working for any position of body content. – KuldipKoradia Nov 05 '19 at 08:02
  • 1
    You saved me man, God knows I have this problem working on since last 3 hours Thank You 1M – Mir Stephen Feb 06 '20 at 05:38
  • Fixed the issue for me as well. Relative positioning for the div wrapper was not needed in my case. – pinglock Aug 23 '20 at 07:26
  • 1
    Update - Relative positioning was important after-all! Without it, landscape orientation on mobile browsers broke the layout. – pinglock Aug 27 '20 at 01:16
  • te amo breoooooh <33333333333333333333333333333333333333333333333 – Angel Nov 25 '20 at 15:54
  • 3
    Hey great answer, though this solves the initial problem, but for any of you got a sticky nav, this makes it not stick anymore! I solved it by putting the sticky nav outside of the wrapper! – Hasintha Abeykoon May 27 '21 at 09:54
  • I initially thought this worked, but that was not the case. Most of these answers address the *symptoms* of the problem. The best solution seems to be to [fix the *cause* of the problem (the `` tag)](https://stackoverflow.com/a/36693202/114558). – rinogo Sep 22 '21 at 15:37
  • @rinogo The `` solution addresses the symptoms as well. Because the horizontal scrollbar still appears, the user just can't scroll, which isn't a perfect solution. – Arad Alvand Mar 19 '22 at 10:44
107

try

html, body {
  overflow-x:hidden 
} 

instead of just

body {
  overflow-x:hidden 
}
Đinh Carabus
  • 3,403
  • 4
  • 22
  • 44
  • 10
    Thanks, but the application of `overflow` anything to `html` and/or `body` in any combination didn't solve the issue. – Indigenuity Jan 11 '13 at 02:57
  • Sorry that it didn't work out for you. Before I answered I made a quick test using your site and applying my suggestion to your css. It fixed the problem for the standard- and dolphin browser on my android phone at least. – Đinh Carabus Jan 11 '13 at 03:11
  • Out of curiousity, what do you use to modify css on your mobile browsers? – Indigenuity Jan 11 '13 at 03:12
  • I dont know if that is possible. I'm also looking for a mobile browser with some sort of developer plugin :) In your case I just downloaded part of your site to make the changes locally on my pc, then uploaded it onto my webserver - very annoying workaround ;) – Đinh Carabus Jan 11 '13 at 03:24
  • 3
    Worked for me. http://eduardd.eu/projects/ezo ( between 480 and 992px footer had a problem with that overflowing image of the woman and towels ) – Eduard Aug 01 '15 at 11:38
  • 4
    Does anyone know why this works, when specifying body{} and html{} separately doesnt? – hamncheez Sep 05 '17 at 19:25
  • 2
    In needed to add `height:100%;` as well, otherwise vertical scroll would not work properly on pages with loading images (which make the page grow in height). – Arno van Oordt Aug 22 '19 at 07:52
  • This worked for me when also including `position: relative` on `body`. – George WS Apr 20 '21 at 00:11
78

VictorS's comment on the accepted answer deserves to be it's own answer because it's a very elegant solution that does, indeed work. And I'll add a tad to it's usefulness.

Victor notes adding position:fixed works.

body.modal-open {
    overflow: hidden;
    position: fixed;
}

And indeed it does. However, it also has a slight side-affect of essentially scrolling to the top. position:absolute resolves this but, re-introduces the ability to scroll on mobile.

If you know your viewport (my plugin for adding viewport to the <body>) you can just add a css toggle for the position.

body.modal-open {
    // block scroll for mobile;
    // causes underlying page to jump to top;
    // prevents scrolling on all screens
    overflow: hidden;
    position: fixed;
}
body.viewport-lg {
    // block scroll for desktop;
    // will not jump to top;
    // will not prevent scroll on mobile
    position: absolute; 
}

I also add this to prevent the underlying page from jumping left/right when showing/hiding modals.

body {
    // STOP MOVING AROUND!
    overflow-x: hidden;
    overflow-y: scroll !important;
}
Community
  • 1
  • 1
Brad
  • 15,361
  • 6
  • 36
  • 57
  • 3
    Is there anyway to get the mobile part to not jump to top? – WraithKenny May 26 '15 at 21:57
  • 1
    What worked for me was turning the element that was supposed to be hidden by overflow from position: absolute to position: fixed. Thankfully. – Chuck Le Butt Jan 12 '16 at 22:58
  • 1
    @WraithKenny - If you want the page to prevent jumping to the top on a mobile device, you can use the following hack'ish/ugly approach. Inside your modal function, make sure you get the current scroll offset before doing anything, than apply the modal style together and also set the top margin of your body equal to the minus of the current offset. Make sure when you remove the modal you, set the margin back to 0 and scroll the page back to the original offset. – Emil Borconi Mar 25 '16 at 15:45
  • 2
    This solution only works in case your modal's content fits into the screen, i.e. you don't require to scroll the modal itself. – Tobias Aug 12 '16 at 05:44
  • There are other fixed and absolute positioned elements on my page as well. Making body `position:fixed or absolute` disturbing their positions as well. Not suitable/working in my case :( – sohaiby Sep 14 '16 at 11:47
  • I think this answers a different question than I intended to ask, but it answers it well. I hadn't intended the question to be about modals, but rather about any arbitrary element on a page overflowing. So `position:fixed` wouldn't be appropriate on many of those elements. The original question didn't really specify that though, so I still think this answer is very helpful. – Indigenuity Feb 06 '18 at 19:56
53

As @Indigenuity states, this appears to be caused by browsers parsing the <meta name="viewport"> tag.

To solve this problem at the source, try the following:

<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">.

In my tests this prevents the user from zooming out to view the overflowed content, and as a result prevents panning/scrolling to it as well.

feidtmb
  • 1,017
  • 9
  • 5
  • 1
    Adding `initial-scale=1` to an existing viewport metatag does indeed fix the problem. Thanks! – JamesWilson Jun 05 '17 at 13:17
  • 15
    For me it was the `minimum-scale=1` that fixed it – jpenna Jul 23 '18 at 10:50
  • This is what actually worked for me after trying everything else. Thanks a lot ! – Harsha Limaye Jul 03 '20 at 11:30
  • 1
    It helps, but not preventing horizontal scrollbar on mobile yet. – Iggy Jun 18 '21 at 14:13
  • Wew, thanks for this. This happened in my case. Only on media queries the whitespaces appear on bottom and right side. You bro deserve a million + and thanks – leipzy Jul 07 '21 at 03:25
  • Much better than the other solutions here - fixing the cause of the problem instead of a symptom. Thanks! – rinogo Sep 22 '21 at 15:38
  • For me this seems to not solve the problem on Chrome Modile – shitpoet Oct 26 '21 at 21:51
  • Wow thanks! The other suggestions were a bit bulky, and I was glad to find such a simple solution. :) – JSman225 Jun 14 '22 at 16:37
  • Any reason this is not the accepted answer? This should be the accepted solution IMO, OP even referenced meta tags. Other solutions strike me as too hacky. – rmolinamir Sep 24 '22 at 08:01
  • This seems to solve the issue for me but now instead of zooming out I can horizontally scroll the whole screen and there's no content to the right... any ideas? – sleighty Aug 11 '23 at 02:26
40

This is the simplest solution to solve horisontal scrolling in Safari.

html, body {
  position:relative;
  overflow-x:hidden;
}
Waltur Buerk
  • 1,348
  • 13
  • 17
  • 2
    It seems to work. But do you have an explanation why this works? – LarS Dec 14 '17 at 06:06
  • 1
    No, it finally didn't work. I ended up doing the math and made sure that div's aren't wider than allowed, css calc() helped me here a lot as it allows the mixture of relative widths (vw or %) and absolute widths (px). – LarS Dec 16 '17 at 12:00
  • Ofcourse this is something of a workaround. There is still something overflowing somewhere, it's just cut off now. Try adding a css rule: * { outline: 1px solid red; } If you still can't find the overflowing element, then it's probably caused by a margin somewhere. Try adding * { margin:0 !IMPORTANT; } and see if the overflow disappears. – Waltur Buerk Feb 14 '18 at 13:23
  • Works for me. Interesting that the hidden element changes the body's width. For me, however, this is the case for ALL Safari browsers, not only the mobile ones. Just had to fix a Bootstrap 4 `table-responsive` Bug. This was the solution. – CunningFatalist Mar 01 '18 at 08:37
  • I'm not sure what the guy who said this doesn't work was doing wrong (maybe didn't refresh his cache). This solution absolutely does work. – Tom Walker Aug 27 '18 at 22:47
  • 1
    This is the only thing that helped me hide an absolutely positioned element which animates offscreen – diachedelic Jan 14 '19 at 04:43
  • 2
    I can't believe this is still a problem in 2019. But the solution above totally worked. Thx. – staxim Jun 19 '19 at 20:34
  • 5
    A problem with setting `overflow-x: hidden` on `body` is that `position: sticky` stops working. – powerbuoy Feb 27 '20 at 10:27
  • This solution is not working in IOS 13.0 or above devices. Any solution ? – Erum Dec 14 '20 at 08:50
16
body{
height: 100%;
overflow: hidden !important;
width: 100%;
position: fixed;

works on iOS9

ollio
  • 161
  • 1
  • 3
6

Creating a site wrapper div inside the body and applying the overflow->x:hidden to the wrapper INSTEAD of the body or html fixed the issue.

This worked for me after also adding position: relative to the wrapper.

Isaac F
  • 199
  • 3
  • 7
  • This worked for me. The side effect was that I've got two scroll bars instead of one. The solution was to make it `overflow: hidden` instead of `overflow-x: hidden`. Works on mobile Safari, Chrome, IE11 on OSX and Win. – pop Jun 14 '19 at 12:48
5

Keep the viewport untouched: <meta name="viewport" content="width=device-width, initial-scale=1.0">

Assuming you would like to achieve the effect of a continuous black bar to the right side: #menubar shouldn't exceed 100%, adjust the border radius such that the right side is squared and adjust the padding so that it extends a little more to the right. Modify the following to your #menubar:

border-radius: 30px 0px 0px 30px;
width: 100%; /*setting to 100% would leave a little space to the right */
padding: 0px 0px 0px 10px; /*fills the little gap*/

Adjusting the padding to 10px of course leaves the left menu to the edge of the bar, you can put the remaining 40px to each of the li, 20px on each side left and right:

.menuitem {
display: block;
padding: 0px 20px;
}

When you resize the browser smaller, you would find still the white background: place your background texture instead from your div to body. Or alternatively, adjust the navigation menu width from 100% to lower value using media queries. There are a lot of adjustments to be made to your code to create a proper layout, I'm not sure what you intend to do but the above code will somehow fix your overflowing bar.

Anne
  • 591
  • 2
  • 7
5

No previous single solution worked for me, I had to mix them and got the issue fixed also on older devices (iphone 3).

First, I had to wrap the html content into an outer div:

<html>
  <body>
    <div id="wrapper">... old html goes here ...</div>
  </body>
</html>

Then I had to apply overflow hidden to the wrapper, because overflow-x was not working:

  #wrapper {
    overflow: hidden;
  }

and this fixed the issue.

spaghetticode
  • 343
  • 3
  • 7
4

Adding a wrapper <div> around the entirety of your content will indeed work. While semantically "icky", I added an div with a class of overflowWrap right inside the body tag and then set set my CSS like this:

html, body, .overflowWrap {
overflow-x: hidden;
}

Might be overkill now, but works like a charm!

MBurnette
  • 41
  • 3
4

I encountered the same problem with Android devices but not iOS devices. Managed to resolve by specifying position:relative in the outer div of the absolutely positioned elements (with overflow:hidden for outer div)

Kwok Pan Fung
  • 416
  • 5
  • 6
3

I solved the issue by using overflow-x:hidden; as follows

@media screen and (max-width: 441px){

#end_screen { (NOte:-the end_screen is the wrapper div for all other div's inside it.)
  overflow-x: hidden;
   }
 }

structure is as follows

1st div end_screen >> inside it >> end_screen_2(div) >> inside it >> end_screen_2.

'end_screen is the wrapper of end_screen_1 and end_screen_2 div's

Chuck Le Butt
  • 47,570
  • 62
  • 203
  • 289
vikas etagi
  • 625
  • 1
  • 13
  • 15
3

As subarachnid said overflow-x hidden for both body and html worked Here's working example

**HTML**
<div class="contener">
  <div class="menu">
  das
  </div>
  <div class="hover">
    <div class="img1">
    First Strip
    </div>
     <div class="img2">
    Second Strip
    </div>
</div>
</div>
<div class="baner">
dsa
</div>

**CSS**
body, html{
  overflow-x:hidden;
}
body{
  margin:0;
}
.contener{
  width:100vw;
}
.baner{
   background-image: url("http://p3cdn4static.sharpschool.com/UserFiles/Servers/Server_3500628/Image/abstract-art-mother-earth-1.jpg");
   width:100vw;
   height:400px;
   margin-left:0;
   left:0;
}
.contener{
  height:100px;
}
.menu{
  display:flex;
  background-color:teal;
  height:100%;
  justify-content:flex-end;
  align:content:bottom;
}
.img1{
  width:150px;
  height:25px;
  transform:rotate(45deg);
  background-color:red;
  position:absolute;
  top:40px;
  right:-50px;
  line-height:25px;
  padding:0 20px;
  cursor:pointer;
  color:white;
  text-align:center;
  transition:all 0.4s;
}
.img2{
  width:190px;
  text-align:center;
  transform:rotate(45deg);
  background-color:#333;
  position:absolute;
  height:25px;
  line-height:25px;
  top:55px;
  right:-50px;
  padding:0 20px;
  cursor:pointer;
  color:white;
  transition:all 0.4s;
}
.hover{
  overflow:hidden;
}
.hover:hover .img1{
  background-color:#333;
  transition:all 0.4s;
}
.hover:hover .img2{
  background-color:blue;
  transition:all 0.4s;
}

Link

Skylin R
  • 2,111
  • 1
  • 20
  • 23
3

I had tried many ways from replies in this topic, mostly works but got some side-effect like if I use overflow-x on body,html it might slow/freeze the page when users scroll down on mobile.

use position: fixed on wrapper/div inside the body is good too, but when I have a menu and use Javascript click animated scroll to some section, It's not working.

So, I decided to use touch-action: pan-y pinch-zoom on wrapper/div inside the body. Problem solved.

j.limjinda
  • 128
  • 2
  • 6
3

easiest way to solve this , add

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">

Phakamani Xulu
  • 259
  • 5
  • 14
1

I've just been working on this for a few hours, trying various combinations of things from this and other pages. The thing that worked for me in the end was to make a site wrapper div, as suggested in the accepted answer, but to set both overflows to hidden instead of just the x overflow. If I leave overflow-y at scroll, I end up with a page that only scrolls vertically by a few pixels and then stops.

#all-wrapper {
  overflow: hidden;
}

Just this was enough, without setting anything on the body or html elements.

highfellow
  • 35
  • 8
1

Solution that properly work for mobile device with flex positionning top :

html,body {
    width: 100%;
    margin: 0;
    padding: 0;
}

and in web page :

  <meta name="viewport" content="width=device-width, user-scalable=0">

Don't forget to positioning this css in the different webpage main divs :

height : auto !important;
nonozor
  • 865
  • 2
  • 14
  • 24
1

Setting overflow-x to 'clip' instead of 'hidden' also prevents unwanted scrolling on touch-devices, with wacom-pens, with shift-scrollwheel or any other programmatic scrolling. On the downside, it also prevents programmatic scrolling with javascript.

https://developer.mozilla.org/en-US/docs/Web/CSS/overflow#clip

hetgelaat
  • 11
  • 2
0

The only way to fix this issue for my bootstrap modal (containing a form) was to add the following code to my CSS:

.modal {
    -webkit-overflow-scrolling: auto!important;
}
Tobias
  • 820
  • 7
  • 11
0

step 1: set position to fixed to the element that goes out from the viewport. In my case it is:

.nav-links {
    position:fixed;
    right:0px;
    background-color:rgba(0,0,0, 0.8);
    height:85vh;
    top:8vh;
    display:flex;
    flex-direction:column;
    align-items: center;
    width:40%;
    transform: translateX(100%);
    transition: transform 0.5s ease-in;
}

Step2: add a css property to body and html as:

body, html{
    overflow-x:  hidden;
}

I didn't add any wrapper. Only these two steps worked for me. The project I am working on is an angular project.

Dhiraj Baruah
  • 192
  • 1
  • 8
0

The following works

body,
.innerbodywrapper{
overflow-x: hidden;
position: fixed;
width: 100%;
height: 100vh;
}
Jason Howard
  • 1,464
  • 1
  • 14
  • 43
0

html, body{ overflow-x: hidden; position: relative; } Just try like this where you have added the overflow-hidden.

nullptr
  • 3,701
  • 2
  • 16
  • 40