Prevent scroll below modal window on iOS developed using CSS, HTML. Demo and Download available.
HTML Snippet
</p>
<p>page can scroll...</p>
<p>page can scroll...</p>
<p>yes it can!</p>
</article><input type="checkbox" id="toggleModal" />
<article>
<h1>Prevent scroll below modal window on iOS <span>(99%)</span></h1>
<hr />
<p>Creating websites that works on iOS is...</p>
<h2>Super relaxing</h2>
<img src="https://us-east-1.tchyn.io/snopes-production/uploads/2016/05/monsters-inc.jpg" />
<label for="toggleModal">Open modal<i class="material-icons">launch</i></label>
<p>page can scroll...</p>
<hr />
<h2>Pure joy</h2>
<img src="https://i.ytimg.com/vi/dJWm0TWH7d0/maxresdefault.jpg" />
<label for="toggleModal">Open modal<i class="material-icons">launch</i></label>
<p>page can scroll...</p>
<p>page can scroll...</p>
<p>page can scroll...</p>
<hr />
<h2>No struggle at all</h2>
<img src="https://pixar-planet.fr/wp-content/uploads/2010/04/george-sanderson-personnage-monstres-cie-04.jpg" />
<label for="toggleModal">Open modal<i class="material-icons">launch</i></label>
<p>page can scroll...
<label for="toggleModal"><i class="material-icons">close</i></label>
<div class="modal">
<article>
<h2>Feel free to scroll again</h2>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<a href="#" onclick="alert('ðߑ»ðߑ»ðߑ»ðߑ»ðߑ»')">You can click me if you like</a>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>modal can scroll...</p>
<p>OK stop it!</p>
<img src="https://moviefavourites.files.wordpress.com/2010/12/mike.jpg" />
</article>
CSS Code
// just some styling
@import url("https://fonts.googleapis.com/css?family=Merriweather:300|Open+Sans:400|Material+Icons");
html { box-sizing: border-box; } *,*::before,*::after { box-sizing: inherit; position: relative; }
body { margin: 0;}
img { border-radius: 5px; }
body {-webkit-font-smoothing: antialiased; }
h1,h2 {font-family: Merriweather, serif}
h1 {font-size: 24px; }
h2 {font-size: 18px; }
p,label { font-family: 'Open Sans' }
p { color: #ccc; }
img { width: 100%; }
body {background: whitesmoke; }
hr { border: 0; border-top: 1px solid #ccc; }
article { padding: 20px; border-radius: 5px; background: white; box-shadow: 2px 2px 5px rgba(0,0,0,0.3); max-width: 420px; margin: 16px auto; }
label { display: block; width: 100%; border-radius: 5px; background-color: dodgerblue; color: white; padding: 8px; cursor: pointer; }
label i { vertical-align: bottom; float: right; }
h1 span {font-size: 40%; color: #ccc;}
[id="toggleModal"]{position:fixed;left:-20px; visibility: hidden; }
[id="toggleModal"]:not(:checked) ~ .modal,
[id="toggleModal"]:not(:checked) ~ label{ display: none; }
.modal {
padding: 10px;
background: rgba(0,0,0,0.7);
position: fixed; top: 0; right: 0; bottom: 0; left: 0;
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
body > label {
position: fixed; top: 40px; right: 40px; width: auto;
z-index:1;
}
JavaScript Snippet
// ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
// Note! I'm still experimenting â code could change
//
// A not 100% bulletproof attempt to prevent iOS from
// page content below modal window while allowing scroll
// inside the modal itself.
//
// ðߏ� Does not require position fixed or overflow
// hidden on the body tag
//
// ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
(IIFE => {
const check = document.querySelector('input');
const modal = document.querySelector('.modal');
// prevent page scroll
let scrollLock = false;
// toggle scroll lock state
check.addEventListener('change', e => { scrollLock = e.target.checked });
// modal window listeners
modal.addEventListener('touchstart', onePixelHack, { passive: false });
modal.addEventListener('scroll', onePixelHack, { passive: false });
// One pixel hack
// it seems iOS won't allow scrolling in modal if at top or bottom
// â why in that case we shift scrollTop by one pixel (up or down)
function onePixelHack(e){
if(!scrollLock) return;
const atTop = modal.scrollTop === 0;
const atBot = modal.scrollHeight - modal.scrollTop === modal.offsetHeight;
if(atTop||atBot){ modal.scrollTop += atTop ? 1 : -1; e.preventDefault(); }
}
// About the passive event option:
// As the browser does not know if an event will be cancled it needs to
// run the entire handler script before proceeding. Setting passive
// to true tells the browser the handler will not cancel the event and
// can proceed without awaiting execution.
//
// In this case we want to cancel and as iOS 11.1 by default sets passive
// to true on touchstart and touchmove we need to override it.
})();
Preview
Leave a Reply