voorkomen dat het lichaam scrollen, maar toestaan ​​van overlay scrollen

Ik heb op zoek gegaan naar een “lightbox” -type-oplossing waarmee dit het mogelijk maakt, maar er nog geen heb gevonden (alsjeblieft, suggereert als je dat weet).

Het gedrag dat ik probeer te maken, is net als wat je zou zien op Pinterest bij het klikken op een afbeelding. De overlay is schuifbaar (zoals in de hele overlay beweegt als een pagina bovenop een pagina ) maar het lichaam achter de overlay is vast.

Ik heb geprobeerd dit te maken met alleen CSS (IE A divOverlay bovenop de hele pagina en het lichaam met overflow: hidden) , maar het verhindert niet divvan scrolable.

Hoe de body / pagina te behouden van scrollen, maar blijf scrollen in de container Fullscreen?


1, Autoriteit 100%

theorie

Kijkend naar de huidige implementatie van de Pinterest-site (het kan in de toekomst veranderen), wanneer u de overlay opent noscrollKlasse wordt toegepast op de bodyElement en overflow: hiddenis ingesteld, dus bodyis niet langer schuifbaar.

De overlay (on-the-fly of reeds in de pagina gemaakt en zichtbaar gemaakt via display: block, het maakt geen verschil) heeft position : fixedEN overflow-y: scroll, met top, left, rightEN bottomEigenschappen Set Naar 0: Deze stijl maakt de overlay de hele viewport.

De divin de overlay is in plaats daarvan alleen in position: staticdan de verticale schuifbalk die u ziet, is gerelateerd aan dat element. Als gevolg hiervan is de inhoud schuifbaar maar overlay blijft vast.

Als u de zoom sluit, verbergt u de overlay (via display: none) en kunt u deze ook volledig verwijderen via javascript (of alleen de inhoud erin, het is aan u hoe u deze invoegt ).

Als laatste stap moet je ook de klasse noscrollnaar de bodyverwijderen (zodat de eigenschap overflow terugkeert naar zijn oorspronkelijke waarde)


Code

Codepen-voorbeeld

(het werkt door het aria-hiddenattribuut van de overlay te wijzigen om het te tonen en te verbergen en om de toegankelijkheid te vergroten).

Mark-up
(knop openen)

<button type="button" class="open-overlay">OPEN LAYER</button>

(overlay en sluitknop)

<section class="overlay" aria-hidden="true">
  <div>
    <h2>Hello, I'm the overlayer</h2>
    ...   
    <button type="button" class="close-overlay">CLOSE LAYER</button>
  </div>
</section>

CSS

.noscroll { 
  overflow: hidden;
}
.overlay { 
   position: fixed; 
   overflow-y: scroll;
   top: 0; right: 0; bottom: 0; left: 0; }
[aria-hidden="true"]  { display: none; }
[aria-hidden="false"] { display: block; }

Javascript(vanilla-JS)

var body = document.body,
    overlay = document.querySelector('.overlay'),
    overlayBtts = document.querySelectorAll('button[class$="overlay"]');
[].forEach.call(overlayBtts, function(btt) {
  btt.addEventListener('click', function() { 
     /* Detect the button class name */
     var overlayOpen = this.className === 'open-overlay';
     /* Toggle the aria-hidden state on the overlay and the 
        no-scroll class on the body */
     overlay.setAttribute('aria-hidden', !overlayOpen);
     body.classList.toggle('noscroll', overlayOpen);
     /* On some mobile browser when the overlay was previously
        opened and scrolled, if you open it again it doesn't 
        reset its scrollTop property */
     overlay.scrollTop = 0;
  }, false);
});

Ten slotte, hier is een ander voorbeeld waarin de overlay wordt geopend met een fade-in-effect door een CSS transitiontoegepast op de opacityeigendom. Ook een padding-rightwordt toegepast om een ​​reflow op de onderliggende tekst te voorkomen wanneer de schuifbalk verdwijnt.

COCEIPEN VOORBEELD (FADE)

CSS

.noscroll { overflow: hidden; }
@media (min-device-width: 1025px) {
    /* not strictly necessary, just an experiment for 
       this specific example and couldn't be necessary 
       at all on some browser */
    .noscroll { 
        padding-right: 15px;
    }
}
.overlay { 
     position: fixed; 
     overflow-y: scroll;
     top: 0; left: 0; right: 0; bottom: 0;
}
[aria-hidden="true"] {    
    transition: opacity 1s, z-index 0s 1s;
    width: 100vw;
    z-index: -1; 
    opacity: 0;  
}
[aria-hidden="false"] {  
    transition: opacity 1s;
    width: 100%;
    z-index: 1;  
    opacity: 1; 
}

2, Autoriteit 12%

Als u overscrolling op iOS wilt voorkomen, kunt u een vaste positie toevoegen aan uw .noscroll-klasse

body.noscroll{
    position:fixed;
    overflow:hidden;
}

Antwoord 3, autoriteit 9%

overscroll-behaviorcss-eigenschap maakt het mogelijk om het standaard overloop-scrollgedrag van de browser te negeren bij het bereiken van de boven-/onderkant van inhoud.

Voeg gewoon de volgende stijlen toe aan de overlay:

.overlay {
   overscroll-behavior: contain;
   ...
}

Codepen-demo

Werkt momenteel in Chrome, Firefox en IE(caniuse)

Raadpleeg voor meer informatie het artikel van Google-ontwikkelaars.


Antwoord 4, autoriteit 7%

Gebruik overflow: hidden;niet op body. Het scrolt alles automatisch naar boven. JavaScript is ook niet nodig. Maak gebruik van overflow: auto;. Deze oplossing werkt zelfs met mobiele Safari:

HTML-structuur

<div class="overlay">
    <div class="overlay-content"></div>
</div>
<div class="background-content">
    lengthy content here
</div>

Styling

.overlay{
    position: fixed;
    top: 0px;
    left: 0px;
    right: 0px;
    bottom: 0px;
    background-color: rgba(0, 0, 0, 0.8);
    .overlay-content {
        height: 100%;
        overflow: scroll;
    }
}
.background-content{
    height: 100%;
    overflow: auto;
}

Bekijk de demo hieren de broncode hier.

Bijwerken:

Voor mensen die de spatiebalk op het toetsenbord willen, pagina omhoog/omlaag om te werken: je moet je concentreren op de overlay, bijvoorbeeld door erop te klikken, of handmatig JS erop focussen vóór dit deel van de divreageert op toetsenbord. Hetzelfde geldt voor wanneer de overlay is “uitgeschakeld”, omdat de overlay gewoon naar de zijkant wordt verplaatst. Anders voor de browser zijn dit slechts twee normale divs en zou het niet weten waarom het zich op een van hen zou moeten concentreren.


Antwoord 5, autoriteit 7%

De meeste oplossingen hebben het probleem dat ze de scrollpositie niet behouden, dus ik heb gekeken hoe Facebook het doet. Naast het instellen van de onderliggende inhoud op position: fixed, stellen ze de bovenkant ook dynamisch in om de schuifpositie te behouden:

scrollPosition = window.pageYOffset;
mainEl.style.top = -scrollPosition + 'px';

Als u de overlay vervolgens weer verwijdert, moet u de schuifpositie opnieuw instellen:

window.scrollTo(0, scrollPosition);

Ik heb een klein voorbeeld gemaakt om deze oplossing te demonstreren

let overlayShown = false;
let scrollPosition = 0;
document.querySelector('.toggle').addEventListener('click', function() {
  if (overlayShown) {
		showOverlay();
  } else {
    removeOverlay();
  }
  overlayShown = !overlayShown;
});
function showOverlay() {
    scrollPosition = window.pageYOffset;
  	const mainEl = document.querySelector('.main-content');
    mainEl.style.top = -scrollPosition + 'px';
  	document.body.classList.add('show-overlay');
}
function removeOverlay() {
		document.body.classList.remove('show-overlay');
  	window.scrollTo(0, scrollPosition);
    const mainEl = document.querySelector('.main-content');
    mainEl.style.top = 0;
}
.main-content {
  background-image: repeating-linear-gradient( lime, blue 103px);
  width: 100%;
  height: 200vh;
}
.show-overlay .main-content {
  position: fixed;
  left: 0;
  right: 0;
  overflow-y: scroll; /* render disabled scroll bar to keep the same width */
}
.overlay {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.3);
  overflow: auto;
}
.show-overlay .overlay {
  display: block;
}
.overlay-content {
  margin: 50px;
  background-image: repeating-linear-gradient( grey, grey 20px, black 20px, black 40px);
  height: 120vh;
}
.toggle {
  position: fixed;
  top: 5px;
  left: 15px;
  padding: 10px;
  background: red;
}
/* reset CSS */
body {
  margin: 0;
}
<main class="main-content"></main>
  <div class="overlay">
    <div class="overlay-content"></div>
  </div>
  <button class="toggle">Overlay</button>

Antwoord 6, autoriteit 5%

Het is vermeldenswaard dat het soms niet werkt om “overflow:hidden” aan de body-tag toe te voegen. In die gevallen moet u de eigenschap ook aan de html-tag toevoegen.

html, body {
    overflow: hidden;
}

Antwoord 7

Als je wilt dat een ouder (de body in dit geval) voorkomt dat deze scrolt wanneer een kind (de overlay in dit geval) scrolt, maak dan in het algemeen van het kind een broer of zus van de ouder om te voorkomen dat de scroll-gebeurtenis opborrelen bij de ouder. In het geval dat de ouder het lichaam is, vereist dit een extra verpakkingselement:

<div id="content">
</div>
<div id="overlay">
</div>

Zie Scroll bepaalde DIV-inhoud met de hoofdschuifbalk van de browserom te zien hoe het werkt.


8

Het gedrag dat u wilt voorkomen, wordt Scroll Chaining genoemd. Om het uit te schakelen, stelt u

in

overscroll-behavior: contain;

op uw overlay in CSS.


9

U kunt dit eenvoudig doen met een aantal “nieuwe” CSS en JQUERY.

In eerste instantie: body {... overflow:auto;}
Met jQuery kun je dynamisch schakelen tussen ‘overlay’ en ‘lichaam’. Wanneer u op ‘lichaam’ gebruikt, gebruikt u

body {
   position: static;
   overflow: auto;
}

Gebruik bij ‘Overlay’

body {
   position: sticky;
   overflow: hidden;
}

JQuery voor de schakelaar (‘lichaam’ – & gt; ‘overlay’):

$("body").css({"position": "sticky", "overflow": "hidden"});

JQuery voor de switch(‘overlay’->’body’):

$("body").css({"position": "static", "overflow": "auto"});

Antwoord 10

Probeer voor aanraakapparaten een transparante div van 1px breed, 101vhmin-height toe te voegen aan de wrapper van de overlay. Voeg vervolgens -webkit-overflow-scrolling:touch; overflow-y: auto;naar de wrapper. Dit zorgt ervoor dat mobiele safari denkt dat de overlay scrollbaar is, waardoor de aanrakingsgebeurtenis van het lichaam wordt onderschept.

Hier is een voorbeeldpagina. Open op mobiele safari: http://www.originalfunction.com/overlay.html

https://gist.github.com/YarGnawh/90e0647f21b5fa78d2f678909673507f


Antwoord 11

Ik vond deze vraag om een probleem op te lossen dat ik had met mijn pagina op Ipad en Iphone – body scrolde toen ik vaste div weergaf als pop-up met afbeelding.

Sommige antwoorden zijn goed, maar geen van hen heeft mijn probleem opgelost. Ik vond de volgende blogpost van Christoffer Pettersson. De daar gepresenteerde oplossing hielp bij het probleem dat ik had met iOS-apparaten en het hielp bij mijn probleem met scrollen op de achtergrond.

Zes dingen die ik heb geleerd over het scrollen met elastiekjes in iOS Safari

Zoals gesuggereerd, neem ik de belangrijkste punten van de blogpost op voor het geval de link verouderd raakt.

“Om uit te schakelen dat de gebruiker de achtergrondpagina kan scrollen terwijl het menu” is geopend “, is het mogelijk om te bepalen welke elementen moeten worden gescrold of niet, door een javascript en een CSS-klasse toe te passen.

Gebaseerd op deze Stackoverflow Antwoord U kunt besturing dat elementen met de uitschakeling-scrollen niet mogen
Voer hun standaard scroll-actie uit wanneer de touchsmove-gebeurtenis wordt geactiveerd. “

document.ontouchmove = function ( event ) {
    var isTouchMoveAllowed = true, target = event.target;
    while ( target !== null ) {
        if ( target.classList && target.classList.contains( 'disable-scrolling' ) ) {
            isTouchMoveAllowed = false;
            break;
        }
        target = target.parentNode;
    }
    if ( !isTouchMoveAllowed ) {
        event.preventDefault();
    }
};

en plaats vervolgens de schakelklasse op de pagina DIV:

<div class="page disable-scrolling">

12

Als de intentie is om uit te schakelen op Mobile / Touch-apparaten, dan is de meest eenvoudige manier om het te doen is het gebruik van touch-action: none;.

Voorbeeld:

const app = document.getElementById('app');
const overlay = document.getElementById('overlay');
let body = '';
for (let index = 0; index < 500; index++) {
  body += index + '<br />';
}
app.innerHTML = body;
app.scrollTop = 200;
overlay.innerHTML = body;
* {
  margin: 0;
  padding: 0;
}
html,
body {
  height: 100%;
}
#app {
  background: #f00;
  position: absolute;
  height: 100%;
  width: 100%;
  overflow-y: scroll;
  line-height: 20px;
}
#overlay {
  background: rgba(0,0,0,.5);
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 100%;
  padding: 0 0 0 100px;
  overflow: scroll;
}
<div id='app'></div>
<div id='overlay'></div>

13

Ik wil graag toevoegen aan eerdere antwoorden omdat ik dat probeerde te doen, en een lay-out brak zodra ik het lichaam naar positie heb geschakeld: vast. Om dat te voorkomen, moest ik ook de hoogte van het lichaam instellen tot 100%:

function onMouseOverOverlay(over){
    document.getElementsByTagName("body")[0].style.overflowY = (over?"hidden":"scroll");
    document.getElementsByTagName("html")[0].style.position = (over?"fixed":"static");
    document.getElementsByTagName("html")[0].style.height = (over?"100%":"auto");
}

14

Gebruik de volgende HTML:

<body>
  <div class="page">Page content here</div>
  <div class="overlay"></div>
</body>

Dan JavaScript om te onderscheppen en stoppen met scrollen:

$(".page").on("touchmove", function(event) {
  event.preventDefault()
});

Des dan om dingen weer normaal te krijgen:

$(".page").off("touchmove");


15

Probeer dit

var mywindow = $('body'), navbarCollap = $('.navbar-collapse');    
navbarCollap.on('show.bs.collapse', function(x) {
                mywindow.css({visibility: 'hidden'});
                $('body').attr("scroll","no").attr("style", "overflow: hidden");
            });
            navbarCollap.on('hide.bs.collapse', function(x) {
                mywindow.css({visibility: 'visible'});
                $('body').attr("scroll","yes").attr("style", "");
            });

16

In mijn geval werkte geen van deze oplossingen op de iPhone (iOS 11.0).

De enige effectieve oplossing die aan al mijn apparaten werkt, is deze – iOS-10-safari-voorkom-scroll-achter- A-vaste overlay-en-onderhoud-scroll-positie


17

Als u de Body / HTML-scroll wilt stoppen, Toevoegen als volgt te luiden

CSS

   html, body {
        height: 100%;
    }
    .overlay{
        position: fixed;
        top: 0px;
        left: 0px;
        right: 0px;
        bottom: 0px;
        background-color: rgba(0, 0, 0, 0.8);
        .overlay-content {
            height: 100%;
            overflow: scroll;
        }
    }
    .background-content{
        height: 100%;
        overflow: auto;
    }

html

   <div class="overlay">
        <div class="overlay-content"></div>
    </div>
    <div class="background-content">
        lengthy content here
    </div>

In principe zou je het kunnen doen zonder JS.

Het hoofdidee is om HTML / Lichaam toe te voegen met Hoogte: 100% en overloop: Auto.
En in uw overlay, kunt u scrollen op of uitschakelen op basis van uw vereiste.

Ik hoop dat dit helpt!


18

Gebruik onderstaande code voor het uitschakelen en inschakelen van schuifbalk.

Scroll = (
    function(){
          var x,y;
         function hndlr(){
            window.scrollTo(x,y);
            //return;
          }  
          return {
               disable : function(x1,y1){
                    x = x1;
                    y = y1;
                   if(window.addEventListener){
                       window.addEventListener("scroll",hndlr);
                   } 
                   else{
                        window.attachEvent("onscroll", hndlr);
                   }     
               },
               enable: function(){
                      if(window.removeEventListener){
                         window.removeEventListener("scroll",hndlr);
                      }
                      else{
                        window.detachEvent("onscroll", hndlr);
                      }
               } 
          }
    })();
 //for disabled scroll bar.
Scroll.disable(0,document.body.scrollTop);
//for enabled scroll bar.
Scroll.enable();

Other episodes