Zapobiegaj przewijaniu ciała, ale Zezwalaj na przewijanie nakładek
Szukałem rozwiązania typu "lightbox", które na to pozwala, ale jeszcze nie znalazłem (proszę, sugeruj, jeśli znasz jakieś).
Zachowanie, które próbuję odtworzyć, jest podobne do tego, co można zobaczyć na Pintereście po kliknięciu obrazu. Nakładka jest przewijalna (ponieważ cała nakładka porusza się w górę jak strona na górze strony), ale ciało ZA nakładka jest stała.
Próbowałem stworzyć to za pomocą CSS ( tj. nakładki div
na górze całej strony i body z overflow: hidden
), ale nie uniemożliwia div
przewijania.
Jak zachować treść / stronę przed przewijaniem, ale nadal przewijać wewnątrz kontenera pełnoekranowego?
17 answers
Teoria
Patrząc na bieżącą implementację witryny Pinteresta (może się ona zmienić w przyszłości), po otwarciu nakładki do elementu body
zostanie zastosowana Klasa noscroll
, a overflow: hidden
zostanie ustawiona, więc body
nie będzie już można przewijać.
Nakładka (tworzona w locie lub już wewnątrz strony i widoczna przez display: block
, nie robi różnicy) ma position : fixed
i overflow-y: scroll
, z top
, left
, right
i bottom
właściwości ustawione na 0
: ten styl sprawia, że nakładka wypełnij cały widok.
div
wewnątrz nakładki jest zamiast tego tylko w position: static
wtedy pionowy pasek przewijania, który widzisz, jest powiązany z tym elementem. W rezultacie zawartość jest przewijana, ale nakładka pozostaje stała.
Po zamknięciu zoomu ukrywasz nakładkę (za pomocą display: none
), a następnie możesz ją całkowicie usunąć za pomocą javascript (lub tylko zawartość wewnątrz, od Ciebie zależy, jak ją wstrzyknąć).
Jako ostatni krok musisz również usunąć noscroll
klasę do body
(tak więc właściwość overflow powraca do swojej wartości początkowej)
Kod
(działa poprzez zmianę atrybutu aria-hidden
nakładki w celu pokazania i ukrycia jej oraz zwiększenia jej dostępności).
Znaczniki
(Otwórz przycisk)
<button type="button" class="open-overlay">OPEN LAYER</button>
(nakładka i przycisk zamykania)
<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);
});
Wreszcie, oto kolejny przykład, w którym nakładka otwiera się z efektem zanikania przez CSS transition
zastosowany do właściwości opacity
. Stosuje się również znak padding-right
, aby uniknąć ponownego wlewu tekstu, Gdy pasek przewijania zniknie.
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-27 08:18:41
Jeśli chcesz zapobiec overscrollingowi na ios, możesz dodać pozycję stałą do swojego.Klasa noscroll
body.noscroll{
position:fixed;
overflow:hidden;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-17 07:54:36
Nie używaj overflow: hidden;
na body
. Automatycznie przewija wszystko do góry. JavaScript też nie jest potrzebny. Wykorzystaj overflow: auto;
. To rozwiązanie działa nawet z mobilnym Safari:
Struktura HTML
<div class="overlay">
<div class="overlay-content"></div>
</div>
<div class="background-content">
lengthy content here
</div>
Stylizacja
.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;
}
Zobacz demo tutaj oraz kod źródłowy tutaj.
Update:
Dla osób, które chcą spacji na klawiaturze, strona w górę/w dół do pracy: musisz skupić się na nakładce, np. klikając na nią, lub ręcznie JS skupiając się na nim, zanim ta część div
odpowie na klawiaturę. To samo dotyczy sytuacji, gdy nakładka jest "wyłączona", ponieważ po prostu przesuwa nakładkę na bok. W przeciwnym razie do przeglądarki, są to tylko dwa normalne div
s i nie wiedziałby, dlaczego powinien skupić się na którejkolwiek z nich.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-31 06:47:06
Warto zauważyć, że czasami dodanie "overflow:hidden" do tagu body nie sprawdza się. W takich przypadkach będziesz musiał dodać właściwość do znacznika html.
html, body {
overflow: hidden;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-18 19:58:24
Większość rozwiązań ma problem, że nie zachowują pozycji przewijania, więc przyjrzałem się, jak Facebook to robi. Oprócz Ustawienia zawartości podkładu na position: fixed
ustawiają również dynamicznie górę, aby zachować pozycję przewijania:
scrollPosition = window.pageYOffset;
mainEl.style.top = -scrollPosition + 'px';
Następnie, po ponownym usunięciu nakładki, musisz zresetować pozycję przewijania:
window.scrollTo(0, scrollPosition);
Stworzyłem mały przykład, aby zademonstrować to rozwiązanie
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;
}
<main class="main-content"></main>
<div class="overlay">
<div class="overlay-content"></div>
</div>
<button class="toggle">Overlay</button>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-21 06:38:28
overscroll-behavior
właściwość css pozwala nadpisać domyślne zachowanie przewijania przepełnienia przeglądarki po osiągnięciu górnej / dolnej części zawartości.
Wystarczy dodać następujące style do nakładki:
.overlay {
overscroll-behavior: contain;
...
}
Obecnie działa w Chrome, Firefox i IE (caniuse )
Aby uzyskać więcej informacji sprawdź artykuł programistów google.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 11:07:58
Ogólnie rzecz biorąc, jeśli chcesz, aby rodzic (ciało w tym przypadku) zapobiegał przewijaniu podczas przewijania dziecka (nakładka w tym przypadku), zmień dziecko na rodzeństwo rodzica, aby zapobiec przewijaniu zdarzenia do rodzica. W przypadku, gdy rodzicem jest ciało, wymaga to dodatkowego elementu owijania:
<div id="content">
</div>
<div id="overlay">
</div>
Zobacz przewiń zawartość DIV za pomocą głównego paska przewijania przeglądarki, aby zobaczyć jego działanie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:35
Wybrana odpowiedź jest poprawna, ale ma pewne ograniczenia:
- Super twarde "rzuty" palcem nadal będą przewijać
<body>
w tle - otwarcie wirtualnej klawiatury przez naciśnięcie
<input>
w modalu spowoduje skierowanie wszystkich przyszłych zwojów do<body>
Nie mam poprawki dla pierwszego wydania, ale chciałem rzucić trochę światła na drugi. Co mylące, Bootstrap miał udokumentowany problem z klawiaturą, ale twierdzili, że został naprawiony, powołując się na http://output.jsbin.com/cacido/quiet jako przykład poprawki.
Rzeczywiście, ten przykład działa dobrze na iOS z moimi testami. Jednak aktualizacja go do najnowszej wersji Bootstrap (v4) powoduje jego uszkodzenie.
Próbując dowiedzieć się, jaka była różnica między nimi, zmniejszyłem przypadek testowy, aby nie zależał już od Bootstrap, http://codepen.io/WestonThayer/pen/bgZxBG .
Czynniki decydujące są dziwaczne. Unikanie problemu z klawiaturą wydaje się wymagać, żebackground-color
nie jest ustawione na korzeniu <div>
zawierającym modal i zawartość modalu musi być zagnieżdżona w innym <div>
, który może mieć background-color
ustawiony.
Aby go przetestować, odkomentuj poniższy wiersz w przykładzie Codepen:
.modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 2;
display: none;
overflow: hidden;
-webkit-overflow-scrolling: touch;
/* UNCOMMENT TO BREAK */
/* background-color: white; */
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-15 20:25:12
Dla urządzeń dotykowych, spróbuj dodać przezroczysty div o szerokości 1px, 101vh
min wysokości w opakowaniu nakładki. Następnie dodaj -webkit-overflow-scrolling:touch; overflow-y: auto;
do opakowania. To zmusza mobile safari do myślenia, że nakładka jest przewijalna, przechwytując w ten sposób Zdarzenie dotykowe z ciała.
Https://gist.github.com/YarGnawh/90e0647f21b5fa78d2f678909673507f
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-25 07:52:10
Znalazłem to pytanie, próbując rozwiązać problem, który miałem z mojej strony na iPadzie i Iphone-ciało było przewijanie, gdy wyświetlał stałe div jako popup z obrazem.
Niektóre odpowiedzi są dobre, jednak żadna z nich nie rozwiązała mojego problemu. Znalazłem następujący wpis na blogu Christoffer Pettersson. Przedstawione tam rozwiązanie pomogło problemowi z urządzeniami z systemem iOS i pomogło mojemu problemowi z przewijaniem tła.
Sześć rzeczy, których się nauczyłem o przewijaniu gumki iOS Safari
Jak to sugerowano, że dołączam główne punkty postu na blogu w przypadku, gdy link się nieaktualizuje.
"aby wyłączyć możliwość przewijania strony w tle podczas "menu jest otwarte", można kontrolować, które elementy powinny być przewijane, stosując niektóre JavaScript i klasę CSS.
Na podstawie odpowiedzi Stackoverflow można kontrolować, że elementy z wyłączonym przewijaniem nie powinny wykonaj domyślną akcję przewijania podczas zdarzenia touchmove jest uruchomiony."
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();
}
};
A następnie umieść klasę disable-scrolling na stronie div:
<div class="page disable-scrolling">
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:45
Chciałbym dodać do poprzednich odpowiedzi, ponieważ próbowałem to zrobić, a jakiś layout się zepsuł, gdy tylko zmieniłem ciało na position: fixed. Aby tego uniknąć, musiałem również ustawić wysokość ciała na 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");
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-08 08:52:36
Użyj następującego kodu HTML:
<body>
<div class="page">Page content here</div>
<div class="overlay"></div>
</body>
Następnie JavaScript, aby przechwycić i zatrzymać przewijanie:
$(".page").on("touchmove", function(event) {
event.preventDefault()
});
Potem żeby wszystko wróciło do normy:
$(".page").off("touchmove");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-09 11:45:44
Zachowanie, któremu chcesz zapobiec nazywa się scroll chaining. Aby go wyłączyć, Ustaw
overscroll-behavior: contain;
Na Twojej nakładce w CSS.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-24 14:23:12
Jeśli intencją jest wyłączenie na urządzeniach mobilnych/ dotykowych, najprostszym sposobem jest użycie touch-action: none;
.
Przykład:
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>
(przykład nie działa w kontekście przepełnienia stosu. Będziesz musiał odtworzyć go na samodzielnej stronie.)
Jeśli chcesz wyłączyć przewijanie kontenera #app
, po prostu dodaj touch-action: none;
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-22 13:06:34
Spróbuj tego
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", "");
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-29 13:23:57
W moim przypadku żadne z tych rozwiązań nie zadziałało na iPhonie (iOS 11.0).
Jedyną skuteczną poprawką, która działa na wszystkich moich urządzeniach, jest Ta - IOS-10-safari-prevent-scrolling-behind-a-fixed-overlay-and-maintain-scroll-position
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-22 13:17:12
Użyj poniższego kodu, aby wyłączyć i włączyć pasek przewijania.
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();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-20 15:37:52