ป้องกันการเลื่อนของร่างกาย แต่อนุญาตให้เลื่อนภาพซ้อนทับ


446

ฉันค้นหาโซลูชันประเภท "lightbox" ที่อนุญาตสิ่งนี้ แต่ยังไม่พบโซลูชัน (โปรดแนะนำถ้าคุณรู้ว่ามี)

พฤติกรรมที่ฉันพยายามสร้างขึ้นใหม่ก็เหมือนกับสิ่งที่คุณเห็นที่Pinterestเมื่อคลิกที่ภาพ ภาพซ้อนทับสามารถเลื่อนได้ ( เช่นเดียวกับภาพซ้อนทับทั้งหมดเลื่อนขึ้นเหมือนหน้าบนสุดของหน้า ) แต่เนื้อความด้านหลังภาพซ้อนได้รับการแก้ไข

ฉันพยายามสร้างสิ่งนี้ด้วย CSS ( เช่นdivภาพซ้อนทับด้านบนของทั้งหน้าและเนื้อหาoverflow: hidden ) แต่มันไม่ได้ป้องกันไม่ให้divเลื่อนได้

วิธีการป้องกันไม่ให้ร่างกาย / หน้าเลื่อน แต่ยังคงเลื่อนภายในภาชนะเต็มหน้าจอ?


นี่ไม่ใช่แค่ปลั๊กอิน "โอเวอร์เลย์" อย่างลบล้างโดยใช้ตำแหน่งที่แก้ไขด้วยการเลื่อนมากเกินไปหรือไม่
ggzone

3
ลิงก์ไปยัง Pinterest ไม่ได้ช่วยเนื่องจากเนื้อหาอยู่ด้านหลังกำแพงการลงชื่อ
2540625

4
การอัปเดต 2017:แม้ว่าคุณจะลงชื่อเข้าใช้ Pinterest สิ่งที่คุณพบคือเอฟเฟ็กต์ภาพซ้อนทับที่อธิบายใน OP ไม่มีอยู่อีกต่อไป - แทนเมื่อคุณคลิกที่ภาพที่คุณเพิ่งนำทางไปยังหน้าธรรมดาที่แสดงภาพขนาดใหญ่
Annabel

คำตอบ:


624

ทฤษฎี

ดูการใช้งานปัจจุบันของเว็บไซต์ pinterest (อาจมีการเปลี่ยนแปลงในอนาคต) เมื่อคุณเปิดการซ้อนทับnoscrollชั้นจะถูกนำไปใช้กับbodyองค์ประกอบและการoverflow: hiddenตั้งค่าจึงbodyไม่สามารถเลื่อนได้อีกต่อไป

ซ้อนทับ (สร้างขึ้นบนเครื่องบินหรือมีอยู่แล้วภายในหน้าและทำให้มองเห็นผ่านทางdisplay: blockก็จะทำให้ไม่แตกต่างกัน) มีposition : fixedและoverflow-y: scrollมีtop, left, rightและbottomคุณสมบัติการตั้งค่าให้0: แบบนี้จะทำให้การซ้อนทับเติมวิวพอร์ตทั้งหมด

divภายในซ้อนทับแทนเพียงในposition: staticแล้วเลื่อนแนวตั้งที่คุณเห็นเป็นเรื่องที่เกี่ยวข้องกับองค์ประกอบที่ ดังนั้นเนื้อหาจึงสามารถเลื่อนได้ แต่การซ้อนทับยังคงอยู่

เมื่อคุณปิดการซูมคุณซ่อนการซ้อนทับ (ผ่านdisplay: none) และจากนั้นคุณสามารถลบออกทั้งหมดผ่าน javascript (หรือเฉพาะเนื้อหาที่อยู่ภายในขึ้นอยู่กับคุณว่าจะอัดมันอย่างไร)

ในขั้นตอนสุดท้ายคุณต้องลบnoscrollคลาสไปที่body(ดังนั้นคุณสมบัติโอเวอร์โฟลจะกลับไปเป็นค่าเริ่มต้น)


รหัส

ตัวอย่าง Codepen

(ใช้งานได้โดยเปลี่ยนaria-hiddenคุณลักษณะของการซ้อนทับเพื่อแสดงและซ่อนและเพิ่มการเข้าถึง)

มาร์กอัป
(ปุ่มเปิด)

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

(ปุ่มวางซ้อนและปิด)

<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);

});

สุดท้ายนี้เป็นอีกตัวอย่างหนึ่งที่โอเวอร์เลย์เปิดขึ้นพร้อมเอฟเฟกต์จางโดย CSS ที่transitionใช้กับopacityคุณสมบัติ นอกจากนี้ยังpadding-rightใช้เพื่อหลีกเลี่ยงการ reflow กับข้อความต้นแบบเมื่อแถบเลื่อนหายไป

ตัวอย่าง Codepen (จาง)

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; 
}

6
นี่คือคำตอบที่ถูกต้อง บางคนควรให้เครื่องหมายถูกเนื่องจากถูกต้อง
Scoota P

64
สิ่งนี้ถูกต้องอย่างแน่นอน แต่ควรได้รับการเตือนว่าไม่สามารถใช้งานได้ในซาฟารีมือถือ พื้นหลังจะยังคงเลื่อนและภาพซ้อนทับของคุณจะได้รับการแก้ไข
a10s

20
มันใช้งานได้ดี คอนเทนเนอร์ viewport ที่เลื่อนdivได้จะต้องมีสไตล์ CSS position:fixedและมีการเลื่อนในแนวตั้งมากเกิน ฉันใช้เรียบร้อยแล้วoverflow-y:auto;และสำหรับการเลื่อนโมเมนตัม / ความเฉื่อยของ iOS ฉันเพิ่ม-webkit-overflow-scrolling:touch;CSS ฉันใช้display:block;, width:100%;และheight:100%;CSS เพื่อให้มีวิวพอร์ตเต็มหน้า
Slink

10
ขอโทษฉันไม่เข้าใจ. การตั้งค่าให้โอเวอร์โฟลว์: ซ่อนไม่ปิดใช้งานการเลื่อนร่างกายแบบยืดหยุ่นบน iPad iOS7 ของฉัน ดังนั้นฉันต้องเพิ่มใน js ของฉัน: document.body.addEventListener ('touchmove', ฟังก์ชัน (เหตุการณ์) {event.preventDefault ();}, เท็จ); ซึ่ง SADLY ปิดใช้งานองค์ประกอบทั้งหมดจากการเลื่อนได้เช่นกัน ยังไม่พบวิธีแก้ปัญหาใด ๆ (โดยไม่มีปลั๊กอินเสริม)
Garavani

22
หากผู้ใช้เลื่อนร่างกายลงไปด้านล่างเมื่อเปิดใช้งานการซ้อนทับสิ่งนี้จะทำให้ร่างกายกระโดดขึ้นไปด้านบนเมื่อคุณตั้งค่าการล้น: ซ่อน; มีวิธีใดบ้างไหม?
Björn Andersson

75

หากคุณต้องการป้องกันการโอเวอร์คล็อกบน iOS คุณสามารถเพิ่มตำแหน่งที่คงที่ในคลาส. nrollroll ของคุณ

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

106
ด้วยวิธีนี้เนื่องจากตำแหน่งคงที่ร่างกายจะเลื่อนไปที่ด้านบนของเนื้อหาของคุณโดยอัตโนมัติ สิ่งนี้อาจรบกวนผู้ใช้ของคุณ
tzi

5
ปัญหาอีกประการของการใช้position:fixedคือการเปลี่ยนขนาดตัวเครื่องหลักของฉัน บางทีมันอาจขัดแย้งกับ CSS อื่น ๆ แต่overflow:hiddenเป็นสิ่งที่จำเป็น
Dex

3
สิ่งนี้กำลังทำลายการกระโดดโฟกัสเมื่อคุณแท็บผ่านฟิลด์ป้อนข้อมูล
Atav32

@ Atav32 ฟังดูเหมือนปัญหาแยกตำแหน่งและโอเวอร์โฟลว์ไม่ควรส่งผลกระทบต่อลำดับของแท็บ
am80l

@ am80l ขออภัยความคิดเห็นก่อนหน้าของฉันไม่ชัดสุด: ลำดับแท็บใช้งานได้ แต่หน้าจอเปลี่ยนไปเมื่อคุณแท็บผ่านช่องต่างๆใน iOS Safari ( stackoverflow.com/questions/31126330/ … )
Atav32

44

อย่าใช้ในoverflow: hidden; bodyมันเลื่อนทุกอย่างไปด้านบนโดยอัตโนมัติ ไม่จำเป็นต้องใช้ JavaScript เช่นกัน overflow: auto;ทำให้การใช้งานของ โซลูชันนี้ใช้งานได้กับมือถือ Safari:

โครงสร้าง HTML

<div class="overlay">
    <div class="overlay-content"></div>
</div>

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

การออกแบบ

.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;
}

ดูตัวอย่าง ที่นี่และรหัสที่มาที่นี่

ปรับปรุง:

สำหรับผู้ที่ต้องการสเปซบาร์ของแป้นพิมพ์ให้เลื่อนหน้าขึ้น / ลงเพื่อทำงาน: คุณต้องเน้นไปที่ภาพซ้อนทับเช่นคลิกที่มันหรือ JS ที่กำลังโฟกัสอยู่ด้วยตนเองก่อนส่วนนี้divจะตอบสนองต่อคีย์บอร์ด เช่นเดียวกับเมื่อการซ้อนทับถูก "ปิด" เนื่องจากเป็นเพียงการเลื่อนการซ้อนทับไปด้านข้าง มิฉะนั้นสำหรับเบราว์เซอร์สิ่งเหล่านี้เป็นเพียงสองตัวธรรมดาdivและมันก็ไม่รู้ว่าทำไมมันจึงควรให้ความสนใจกับสิ่งใดสิ่งหนึ่ง


5
วิธีแก้ปัญหาที่ยอดเยี่ยม แต่แล้วฉันต้องห่อเนื้อหาทั้งหมดของฉันไว้ใน div ซึ่งฉันไม่ได้ตั้งใจจะทำ ...
Jacob Raccuia

2
นี่คือทางออกที่ดี หากใครมีปัญหาในการนี้คุณอาจต้องเพิ่มhtml, body { height: 100%; }(ในตัวอย่าง) เพื่อให้ทำงานได้อย่างถูกต้อง
John

4
@ user18490 ส่วนมุม / วัสดุไม่มีส่วนเกี่ยวข้องกับความจริงที่ว่าโซลูชันนี้ใช้งานได้
Lucia

10
สิ่งนี้จะทำลายอุปกรณ์มือถือ UX ได้หลายวิธี (เช่น: การซ่อน URL บาร์, การจ่ายเกินขนาดการจ่าย, ... ), แม้แต่สเปซบาร์เพื่อเลื่อนบนเดสก์ท็อป
nuly

2
นี่เป็นตัวเลือกที่แข็งแกร่งกว่า แต่ก็ซับซ้อนกว่าเล็กน้อย ตัวอย่างเช่น PageUp และ PageDown จะไม่สามารถรีเฟรชได้ สิ่งใดก็ตามที่ใช้.offset()ค่าในการคำนวณทำให้สับสน ฯลฯ ...
BlackPanther

42

overscroll-behavior คุณสมบัติ css ช่วยให้สามารถแทนที่พฤติกรรมการเลื่อนล้นเริ่มต้นของเบราว์เซอร์เมื่อถึงด้านบน / ล่างของเนื้อหา

เพียงเพิ่มสไตล์ต่อไปนี้เพื่อวางซ้อน:

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

การสาธิต Codepen

ปัจจุบันสามารถใช้งานได้ใน Chrome, Firefox และ IE ( caniuse) )

สำหรับรายละเอียดเพิ่มเติมตรวจสอบบทความนักพัฒนา Google


4
ฉันมาถึงแล้วตลอดเวลาที่จะบอกคุณว่านี่เป็นการทำงานกับ Chrome, Mozilla และ Opera รุ่นล่าสุด มีเวลาที่ยอดเยี่ยม!
Wannabe JavaGeek

3
บางคนควรเพิ่มความโปรดปรานในสิ่งนี้ นี่คือทางออกที่ถูกต้อง ไม่จำเป็นต้องใช้ JavaScript :)
joseph.l.hunsaker

9
ปัญหาเกี่ยวกับวิธีแก้ไขปัญหานี้คือใช้งานได้เฉพาะเมื่อการซ้อนทับสามารถเลื่อนได้ หากคุณมีคำกริยาและมันทั้งหมดพอดีกับหน้าจอจึงไม่มีการเลื่อนภายใน - มันจะไม่หยุดการเลื่อนร่างกาย และมันก็ไม่สามารถใช้งานได้ใน Safari เลย :)
waterplea

1
ฉันตัดสินด้วยการรวมกันของสิ่งนี้ด้วยoverflow-y: scroll(จากการสาธิต Codepen ของคุณ) จุดที่ยกขึ้นโดย @pokrishka นั้นถูกต้อง แต่ในกรณีของฉันมันไม่ใช่เรื่องน่ากังวล ไม่ว่าในกรณีใดฉันสงสัยว่าการใช้งานของเบราว์เซอร์จะครอบคลุมรายละเอียดนี้ในอนาคตหรือไม่ ฉันพบว่าใน Firefox การปรับขนาดเบราว์เซอร์เพื่อให้คำกริยาไม่พอดีกับหน้าจอแล้วปรับขนาดอีกครั้งเพื่อให้คุณสมบัตินี้ใช้งานได้ (เช่นมีการเลื่อน) แม้หลังจากปรับขนาดเป็นขนาดเต็ม - จนกว่าหน้าจะโหลดซ้ำ , อย่างน้อย.
Marc.2377

33

วิธีแก้ปัญหาส่วนใหญ่มีปัญหาที่พวกเขาไม่รักษาตำแหน่งการเลื่อนดังนั้นฉันจึงดูว่า Facebook ทำอย่างไร นอกเหนือจากการตั้งค่าเนื้อหาที่อยู่ภายใต้การตั้งค่าposition: fixedพวกเขายังตั้งด้านบนแบบไดนามิกเพื่อรักษาตำแหน่งเลื่อน:

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

จากนั้นเมื่อคุณลบการซ้อนทับอีกครั้งคุณต้องรีเซ็ตตำแหน่งการเลื่อน:

window.scrollTo(0, scrollPosition);

ฉันสร้างตัวอย่างเล็ก ๆ น้อย ๆ เพื่อสาธิตวิธีนี้

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>


นี่น่าจะเป็นทางออกที่ดีที่สุดสำหรับฉัน ฉันรู้ว่า Google ใช้กลอุบายแบบเดียวกันในการเลื่อนหน้าและองค์ประกอบที่เคลื่อนไหวบ่อยๆ
forallepsilon

นี่เป็นทางออกเดียวเท่านั้นที่ทำงานได้ถูกต้อง 100% สำหรับฉันฉันหวังว่าฉันจะพบคำตอบนี้ก่อนหน้านี้
user0103

31

เป็นที่น่าสังเกตว่าบางครั้งการเพิ่ม "ล้น: ซ่อน" ในแท็ก body ไม่ทำงาน ในกรณีดังกล่าวคุณจะต้องเพิ่มคุณสมบัติลงในแท็ก html ด้วย

html, body {
    overflow: hidden;
}

สำหรับ iOS คุณต้องตั้งค่าด้วยwidth: 100%; height: 100%;
Gavin

2
สิ่งนี้ไม่ได้แก้ไขปัญหาที่พบในโซลูชันอื่น ๆ สำหรับคำถามนี้ - หากหน้าต่างถูกเลื่อนไปที่ใดก็ได้ แต่ด้านบนของหน้าเมื่อเปิดใช้งานคำกริยามันจะทำให้เลื่อนไปด้านบนของหน้า ฉันพบวิธีแก้ไขปัญหาของ Philipp Mitterer ที่นี่เพื่อเป็นตัวเลือกที่ดีที่สุดที่ครอบคลุมกรณีส่วนใหญ่
CLL

1
ฉันไม่เคยประสบปัญหานี้ที่คุณพูดถึง (ทั้งบนเว็บหรือมือถือ) คุณสามารถแบ่งปันรหัสเต็ม (กับ DOM) ที่ไม่ทำงานในซอหรือ jsbin ได้หรือไม่? ไม่ว่าในกรณีใดฉันก็ระวังในการใช้วิธีแก้ปัญหา Javascript เพื่อแก้ไขปัญหานี้
Francisco Hodge

7

โดยทั่วไปหากคุณต้องการให้ผู้ปกครอง (เนื้อหาในกรณีนี้) เพื่อป้องกันไม่ให้เลื่อนเมื่อเด็ก (การซ้อนทับในกรณีนี้) เลื่อนจากนั้นให้เด็กเป็นพี่น้องของผู้ปกครองเพื่อป้องกันไม่ให้เหตุการณ์เลื่อนขึ้นไป ผู้ปกครอง ในกรณีที่ผู้ปกครองเป็นร่างกายสิ่งนี้ต้องการองค์ประกอบการห่อเพิ่มเติม:

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

ดูการเลื่อนเนื้อหา DIV โดยเฉพาะด้วยแถบเลื่อนหลักของเบราว์เซอร์เพื่อดูการทำงาน


1
ทางออกที่ดีที่สุดความคิด "ออกนอกกรอบ" ที่แท้จริงไม่ใช่แค่ถ้อยคำที่ดีนัก
Mark

หากร่างกายไม่ได้เป็นองค์ประกอบที่เลื่อนกว่าแถบด้านบนจะไม่เลื่อนขึ้นบนมือถือในขณะที่คุณเลื่อนลงไปที่หน้า
Seph Reed

7

คำตอบที่เลือกนั้นถูกต้อง แต่มีข้อ จำกัด บางประการ:

  • "การเหวี่ยง" สุดแรงด้วยนิ้วของคุณจะยังคงเลื่อนอยู่ <body>ในพื้นหลัง
  • การเปิดแป้นพิมพ์เสมือนจริงโดยการแตะ<input>ที่โมดอลจะเป็นการเลื่อนไปยังอนาคตทั้งหมด<body>

ฉันไม่มีการแก้ไขสำหรับปัญหาแรก แต่ต้องการให้แสงสว่างบางอย่างในวินาที อย่างสับสน, Bootstrap เคยมีปัญหาเกี่ยวกับคีย์บอร์ด แต่พวกเขาอ้างว่ามันได้รับการแก้ไข, อ้างถึงhttp://output.jsbin.com/cacido/quietเป็นตัวอย่างของการแก้ไข

อันที่จริงตัวอย่างนั้นทำงานได้ดีบน iOS ด้วยการทดสอบของฉัน อย่างไรก็ตามการอัพเกรดเป็น Bootstrap ล่าสุด (v4) จะทำให้แตก

ในความพยายามที่จะหาความแตกต่างระหว่างพวกเขาฉันได้ลดกรณีทดสอบให้ไม่ต้องพึ่งพา Bootstrap อีกต่อไปhttp://codepen.io/WestonThayer/pen/bgZxBG http://codepen.io/WestonThayer/pen/bgZxBG

ปัจจัยการตัดสินใจเป็นสิ่งที่แปลกประหลาด การหลีกเลี่ยงปัญหาเกี่ยวกับคีย์บอร์ดดูเหมือนว่าต้องการbackground-color ไม่ได้ตั้งค่าไว้ในรูท<div>ที่มีโมดัลและเนื้อหาของโมดัลจะต้องซ้อนกันในอีกอันหนึ่ง<div>ซึ่งสามารถbackground-colorตั้งค่าได้

ในการทดสอบให้ยกเลิกการใส่เครื่องหมายบรรทัดด้านล่างในตัวอย่าง 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; */
}

4

สำหรับอุปกรณ์ระบบสัมผัสลองเพิ่ม101vhdiv ที่มีความกว้าง 1px และความสูงขั้นต่ำในเสื้อคลุมของภาพซ้อนทับ จากนั้นเพิ่ม-webkit-overflow-scrolling:touch; overflow-y: auto;ไปยังเสื้อคลุม เทคนิคนี้เป็นการซาฟารีมือถือในการคิดว่าโอเวอร์เลย์นั้นสามารถเลื่อนได้ดังนั้นจึงสกัดกั้นเหตุการณ์การสัมผัสจากร่างกาย

นี่คือหน้าตัวอย่าง เปิดบนมือถือซาฟารี: http://www.originalfunction.com/overlay.html

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


Jup นั่นเป็นกลอุบาย เพียงแค่ต้องเพิ่ม-webkit-overflow-scrolling:touch;สำหรับแต่ละคอนเทนเนอร์ที่เลื่อนเพื่อสกัดกั้นเหตุการณ์สัมผัส
Mati

ฉันยังสามารถเลื่อนบน iPhone
Simone Zandara

@SeniorSimoneZandara ฉันไม่ได้ วิธีนี้ใช้งานได้ดีเพื่อป้องกันการเลื่อนพื้นหลัง
godblessstrawberry

3

ลักษณะการทำงานที่คุณต้องการป้องกันเรียกว่าการเชื่อมโยงแบบเลื่อน หากต้องการปิดใช้งานให้ตั้งค่า

overscroll-behavior: contain;

ในการวางซ้อนของคุณใน CSS


3

ฉันพบคำถามนี้พยายามแก้ปัญหาที่ฉันมีกับหน้าของฉันบน Ipad และ Iphone - ตัวเครื่องเลื่อนขึ้นเมื่อฉันแสดง div ที่ตายตัวเป็นป๊อปอัปพร้อมรูปภาพ

คำตอบบางคำตอบก็ดี แต่ก็ไม่มีใครแก้ปัญหาของฉันได้ ฉันพบโพสต์บล็อกต่อไปนี้โดย Christoffer Pettersson โซลูชันที่นำเสนอมีปัญหาช่วยฉันด้วยอุปกรณ์ iOS และช่วยแก้ไขปัญหาพื้นหลังเลื่อนของฉัน

หกสิ่งที่ฉันเรียนรู้เกี่ยวกับการเลื่อนแถบยางของ iOS Safari

ตามที่แนะนำฉันรวมจุดสำคัญของการโพสต์บล็อกในกรณีที่ลิงค์ล้าสมัย

"เพื่อปิดการใช้งานที่ผู้ใช้สามารถเลื่อนหน้าพื้นหลังในขณะที่เมนู" เปิด "มันเป็นไปได้ที่จะควบคุมองค์ประกอบที่ควรได้รับอนุญาตให้เลื่อนหรือไม่โดยใช้ JavaScript และ CSS บางระดับ

ตามคำตอบของStackoverflowคุณสามารถควบคุมองค์ประกอบที่มีการปิดใช้งานการเลื่อนไม่ควรดำเนินการเลื่อนเริ่มต้นเมื่อเหตุการณ์ touchmove ถูกทริกเกอร์ "

 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();
    }
};

จากนั้นใส่คลาสปิดการใช้งานการเลื่อนบน div หน้า:

<div class="page disable-scrolling">

2

คุณสามารถทำได้อย่างง่ายดายด้วย "ใหม่" css และ JQuery

ในขั้นต้น: body {... overflow:auto;} ด้วย JQuery คุณสามารถสลับระหว่าง 'โอเวอร์เลย์' และ 'ร่างกาย' แบบไดนามิก เมื่ออยู่ที่ 'ร่างกาย' ให้ใช้

body {
   position: static;
   overflow: auto;
}

เมื่อใช้งาน 'โอเวอร์เลย์'

body {
   position: sticky;
   overflow: hidden;
}

JQuery สำหรับสวิตช์ ('body' -> 'overlay'):

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

JQuery สำหรับสวิตช์ ('โอเวอร์เลย์' -> 'body'):

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

1

ฉันต้องการที่จะเพิ่มคำตอบก่อนหน้านี้เพราะฉันพยายามที่จะทำเช่นนั้นและรูปแบบบางอย่างพังทลายลงทันทีที่ฉันเปลี่ยนร่างกายเป็นตำแหน่ง: แก้ไข เพื่อหลีกเลี่ยงสิ่งนั้นฉันต้องตั้งความสูงของร่างกายเป็น 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");
}

1

ใช้ HTML ต่อไปนี้:

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

จากนั้น JavaScript เพื่อดักจับและหยุดการเลื่อน:

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

จากนั้นเพื่อให้สิ่งต่าง ๆ กลับสู่ปกติ:

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


1

ถ้าเจตนาคือการปิดการใช้งานบนอุปกรณ์ / touch-action: none;สัมผัสมือถือแล้ววิธีที่ง่ายที่สุดที่จะทำคือการใช้

ตัวอย่าง:

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>

(ตัวอย่างไม่ทำงานในบริบทของ Stack Overflow คุณจะต้องสร้างใหม่ในหน้าแบบสแตนด์อะโลน)

หากคุณต้องการที่จะปิดการใช้งานการเลื่อนของภาชนะเพียงเพิ่ม#apptouch-action: none;


1
หากการดำเนินการสัมผัสใช้งานได้จริงบน iOS นั่นคือ และในกรณีนั้นไม่จำเป็นต้องห่อ "แอพ" ทั้งหมดของคุณใน div แยก
powerbuoy

0

ลองนี้

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", "");
            });

0

หากคุณต้องการหยุดเพิ่ม body / html scroll ให้เพิ่มดังต่อไปนี้

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>

โดยทั่วไปคุณสามารถทำได้โดยไม่ต้อง JS

แนวคิดหลักคือการเพิ่ม html / body ที่มีความสูง: 100% และ overflow: auto และภายในภาพซ้อนทับคุณสามารถเปิด / ปิดการเลื่อนได้ตามความต้องการของคุณ

หวังว่านี่จะช่วยได้!


-1

ในกรณีของฉันไม่มีวิธีแก้ไขปัญหาเหล่านี้ใน iPhone (iOS 11.0)

การแก้ไขที่มีประสิทธิภาพเพียงอย่างเดียวที่ทำงานบนอุปกรณ์ทั้งหมดของฉันคืออันนี้ - ios-10-safari-ป้องกัน-scrolling-behind-a-fixed-overlay-and-maintenance-scroll-position


-2

ใช้รหัสด้านล่างเพื่อปิดและเปิดใช้งานแถบเลื่อน

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();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.