How to disable scrolling on mobile Safari?
Asked Answered
P

18

158

I have a long page, and I want to hide the content that goes underneath the "fold", and it should work on iPhone/iPad.

overflow:hidden applied to <body> does not seem to work on mobile Safari. I can't create a wrapper on the whole website to achieve that...

Do you know the solution?

Pylle answered 15/6, 2010 at 16:58 Comment(0)
H
44

After many days trying, I found this solution that worked for me:

touch-action: none;
-ms-touch-action: none;

MDN touch-action docs

Hallah answered 31/8, 2020 at 22:49 Comment(4)
That didn't work for me on iOS 15.3.1, you used these rules on body right?Choli
Update on my question: This seems to have worked when I added this in advance and not by using a class that toggles these rules on and off on the body element.Choli
Note that while touch-action is set to none, touchscreen actions such as panning, pinch-to-zoom, etc. will likely be turned off. MDN touch-action docsVenison
I didn't test using a class to toggle these rules on and off through JavaScript. But using el.style.touchAction = "none" (and back to "") works on iOS 16.Venison
H
142

I had a similar issue and found that applying overflow: hidden; to both html and body solved my problem.

html,
body {
    overflow: hidden;
} 

For iOS 9, you may need to use this instead: (Thanks chaenu!)

html,
body {
    overflow: hidden;
    position: relative;
    height: 100%;
}
Huston answered 3/8, 2013 at 21:30 Comment(9)
This doesn't work on iOS Safari. position: relative is also necessary.Strasbourg
Yes add both relative and overflow to html + bodyAshanti
A word of warning, overflow hidden on the <html> tag will break jQuery's scroll eventKingkingbird
2016: height: 100% is making vertical scrolling not smooth; is better to remove it.Undersize
This doesn't work for me on iOS 9, Safari. Body still scrollable, also after adding position: relative.Innocency
@Innocency I finally got it by doing position: fixed + overflow hidden on body instead of relative. Hope this helps.Unitarianism
@Unitarianism IIRC we also ran position: fixed for some time, but the downside is that that resets the scroll position.Innocency
height: 100% on both html and body fixed it for me on iOS 11.4.Fielding
@AlexHaas Neither position:relative nor height:100% works in IOS.. I wanted to stop body scroll when dragging an element in mobile . overflow:hidden works perfectly in Android phones. Is there any work around to solve thisYahwistic
V
98
body {
  position:relative; // that's it
  overflow:hidden;
}
Volpe answered 30/11, 2012 at 12:42 Comment(5)
In my case adding "position: relative" didn't help but adding "position: fixed" worked.Logos
Yip this worked. I'm building a site where they want the mobile nav to go over the content - but when it's open the content behind the nav in the background still scroll. The other answers with position, overflow & height also worked but with height the page jumps to the top when I open the nav. I guess it's unique to my situation but just thought I'd mention it in case anyone else with overlaid nav have the same problem.Displacement
Where does the wrapper go? How is this a complete answer?Kata
Adding fixed position does address the issue, but it makes the page jump to the top, which is bad for UX if you're implementing this in the background while you present a menu or modal. To make a good UX, you should, before locking position, store the scroll position of the page, and then re-apply it after unlocked.Forename
In my case I had to add "width:100%" to get it workingXimenes
H
44

After many days trying, I found this solution that worked for me:

touch-action: none;
-ms-touch-action: none;

MDN touch-action docs

Hallah answered 31/8, 2020 at 22:49 Comment(4)
That didn't work for me on iOS 15.3.1, you used these rules on body right?Choli
Update on my question: This seems to have worked when I added this in advance and not by using a class that toggles these rules on and off on the body element.Choli
Note that while touch-action is set to none, touchscreen actions such as panning, pinch-to-zoom, etc. will likely be turned off. MDN touch-action docsVenison
I didn't test using a class to toggle these rules on and off through JavaScript. But using el.style.touchAction = "none" (and back to "") works on iOS 16.Venison
C
34

Some solutions listed here had some strange glitches when stretching the elastic scrolling. To fix that I used:

body.lock-position {
  height: 100%;
  overflow: hidden;
  width: 100%;
  position: fixed;
}

Source: http://www.teamtownend.com/2013/07/ios-prevent-scrolling-on-body/

Cynthy answered 25/1, 2017 at 11:14 Comment(2)
This is nice (works better in my case than position: relative) however, the scroll position is lost after restoring default styling (e.g. closing menu).Voyeur
For scroll position you can use js (jquery in this example) do something like this: // on menu open // save window pos $('body').attr( 'data-pos', $(window).scrollTop() ) ; // ... // on menu close // scroll to saved window pos $( window ).scrollTop( $('body').attr( 'data-pos' ) );Cynthy
G
12

Had this issue today on iOS 8 & 9 and it seems that we now need to add height: 100%;

So add

html,
body {
  position: relative;
  height: 100%;
  overflow: hidden;
}
Greenhorn answered 7/1, 2016 at 16:7 Comment(0)
T
6

Its working in Safari browser.

html,
body {
  overflow: hidden;
  position: fixed
}
Tichonn answered 15/11, 2017 at 9:57 Comment(0)
W
5

For me this:

height: 100%; 
overflow: hidden; 
width: 100%; 
position: fixed;

Wasn't enough, i't didn't work on iOS on Safari. I also had to add:

top: 0;
left: 0;
right: 0;
bottom: 0;

To make it work good. Works fine now :)

Weixel answered 18/12, 2017 at 18:45 Comment(0)
F
4

Combining the answers and comments here and this similar question here worked for me.

So posting as a whole answer.

Here's how you need to put a wrapper div around your site content, just inside the <body> tag.

 <!DOCTYPE HTML>
 <html>
 <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     <!-- other meta and head stuff here -->
 <head>
 <body>
     <div class="wrapper">
         <!-- Your site content here -->
     </div>
 </body>
 </html>

Create the wrapper class as below.

.wrapper{
    position:relative; //that's it
    overflow:hidden;
}

I also got the idea from this answer here.

And this answer here also has got some food for thought. Something that probably will work equally good in both desktops and devices.

Fairchild answered 11/6, 2015 at 13:1 Comment(1)
This causes the page to scroll to top for me when the modal gets closed.Raji
S
2

I've worked with <body>and <div class="wrapper">

When popup opens ...

<body> gets a height of 100% and an overflow:hidden

<div class="wrapper"> gets position:relative;overflow:hidden;height:100%;

I use JS/jQuery to get the actual scrollposition of the page and store the value as data-attribut to body

Then i scroll to the scrollposition in the .wrapper DIV (not in window)

Here is my solution:

JS/jQuery:

// when popup opens

$('body').attr( 'data-pos', $(window).scrollTop()); // get actual scrollpos
$('body').addClass('locked'); // add class to body
$('.wrapper').scrollTop( $('body').attr( 'data-pos' ) ); // let wrapper scroll to scrollpos

// when popup close

$("body").removeClass('locked');
$( window ).scrollTop( $('body').attr( 'data-pos' ));

CSS:

body.locked {position:relative;overflow:hidden;height:100%;}
body.locked .wrapper {position:relative;overflow:hidden;height:100%;}

It works well on both sides ... desktop & mobile (iOS).

Solace answered 8/11, 2017 at 22:38 Comment(0)
W
1
html {
  position:relative;
  top:0px;
  left:0px;
  overflow:auto;
  height:auto
}

add this as default to your css

.class-on-html{
  position:fixed;
  top:0px;
  left:0px;
  overflow:hidden;
  height:100%;
}

toggleClass this class to to cut page

when you turn off this class first line will call scrolling bar back

Westberry answered 27/7, 2017 at 9:59 Comment(0)
D
0

Why not wrap the content you don't want shown in an element with a class and set that class to display:none in a stylesheet meant only for the iphone and other handheld devices?

<!--[if !IE]>-->
<link media="only screen and (max-device-width: 480px)" href="small-device.css" type= "text/css" rel="stylesheet">
<!--<![endif]-->
Devonne answered 16/1, 2011 at 1:36 Comment(0)
I
0

It does apply, but it only applies to certain elements within the DOM. for example, it won't work on a table, td, or some other elements, but it will work on a <DIV> tag.
eg:

<body>
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>

Only tested in iOS 4.3.

A minor edit: you may be better off using overflow:scroll so two finger-scrolling does work.

Ichthyology answered 20/8, 2011 at 17:59 Comment(0)
P
0

Here is what I did: I check the body y position , then make the body fixed and adjust the top to the negative of that position. On reverse, I make the body static and set the scroll to the value I recorded before.

var body_x_position = 0;

function disable_bk_scrl(){

    var elb = document.querySelector('body');

    body_x_position = elb.scrollTop;
    // get scroll position in px

    var body_x_position_m = body_x_position*(-1);
    console.log(body_x_position);

    document.body.style.position = "fixed";

    $('body').css({ top: body_x_position_m });

}

function enable_bk_scrl(){  

    document.body.style.position = "static";

    document.body.scrollTo(0, body_x_position);

    console.log(body_x_position);
}
Panchito answered 30/5, 2019 at 20:0 Comment(0)
T
0

A CSS keyword value that resets a property's value to the default specified by the browser in its UA stylesheet, as if the webpage had not included any CSS. For example, display:revert on a <div> would result in display:block.

overflow: revert;

I think this will work properly

Tenno answered 24/9, 2020 at 18:6 Comment(0)
M
0

If you need scroll modal

Modal open

$('body').attr('data-position', $(window).scrollTop());
$('body').css({'overflow' : 'hidden', 'position' : 'fixed'});

Modal close

$('body').css({'overflow' : 'unset', 'position' : 'unset'});
$(window).scrollTop( $('body').attr( 'data-position' ));
Maseru answered 22/10, 2021 at 9:21 Comment(0)
V
0

My version. Works in iOS

 if (isModalWindowClose) {
        document.querySelector('body').style.overflow = '';
        document.querySelector('html').style.overflow = '';
        
        const scrollY = document.body.style.top;
        
        document.querySelector('html').style.height = '';
        document.body.style.position = '';
        document.body.style.left = '';
        document.body.style.top = '';

        window.scrollTo(0, parseInt(scrollY || '0') * -1);

        document.querySelector('html').style['scroll-behavior'] = '';
    } else {
        document.body.style.top = `-${window.scrollY}px`;
        document.querySelector('html').style.height = `${window.innerHeight - 1}px`;
        
        document.body.style.position = 'fixed';
        document.body.style.left = '0';
        
        document.querySelector('body').style.overflow = 'hidden';
        document.querySelector('html').style.overflow = 'hidden';
        
        document.querySelector('html').style['scroll-behavior'] = 'unset';
    }
Veda answered 17/11, 2021 at 13:24 Comment(0)
N
0

I found many of these answers worked at first. But the moment the keyboard was initiated in iOS, it re-enabled the vertical scroll settings.

So I'm having to rebuild a new interface that is keyboardless.

Nari answered 8/11, 2023 at 20:34 Comment(0)
M
-6

Simply change body height < 300px (height of mobile viewport on landspace is around 300px to 500px)

JS

$( '.offcanvas-toggle' ).on( 'click', function() {
    $( 'body' ).toggleClass( 'offcanvas-expanded' );
});

CSS

.offcanvas-expended { /* this is class added to body on click */
    height: 200px;
}
.offcanvas {
    height: 100%;
}
Mccarthyism answered 19/1, 2018 at 10:40 Comment(1)
Not a very elegant solution, and will cause issues on iOS devices that are larger than the specific pixels you end up choosing. A different solution should be used.Sedate

© 2022 - 2024 — McMap. All rights reserved.