Hanya menonaktifkan gulir tidak menyembunyikannya?

198

Saya mencoba menonaktifkan html / body scrollbar dari orang tua ketika saya menggunakan lightbox. Kata utama di sini adalah disable . Saya tidak ingin menyembunyikannya overflow: hidden;.

Alasan untuk ini adalah yang overflow: hiddenmembuat situs melompat dan mengambil area tempat gulungan itu.

Saya ingin tahu apakah mungkin untuk menonaktifkan scrollbar sementara masih menunjukkannya.

Dejan.S
sumber
1
Haruskah pengguliran bisa dilakukan? (Apakah lightbox memiliki scrollbar?)
Šime Vidas
situs mendapat scrolling tetapi saya hanya ingin menonaktifkannya ketika lightbox terbuka. saya hanya ingin tahu apakah mungkin untuk menonaktifkan scrollbar saat menunjukkannya. tidak ada yang diperlukan seperti bagaimana melakukannya di lightbox atau apa pun.
Dejan.S
apa masalah menggunakan lightbox dengan scrollbar?
Manny
1
@Jejan Karena saya tahu cara menonaktifkan semua scrolling - yang akan menonaktifkan scrollbar utama, tetapi juga yang ada di lightbox ...
Šime Vidas
1
Tolong jangan edit jawaban kembali ke posting ini. Bagian jawaban di bawah ini untuk jawaban. Jika Anda memiliki jawaban untuk pertanyaan Anda yang berbeda dari jawaban di bawah, Anda dapat menambahkan solusi Anda sendiri dalam pemilihan jawaban.
intcreator

Jawaban:

173

Jika halaman di bawah overlayer dapat "diperbaiki" di bagian atas, saat Anda membuka overlay yang dapat Anda atur

body { position: fixed; overflow-y:scroll }

Anda masih harus melihat scrollbar kanan tetapi kontennya tidak dapat digulir. Saat Anda menutup overlay, kembalikan properti ini dengan

body { position: static; overflow-y:auto }

Saya hanya mengusulkan cara ini hanya karena Anda tidak perlu mengubah acara gulir

Memperbarui

Anda juga bisa melakukan sedikit perbaikan: jika Anda mendapatkan document.documentElement.scrollTopproperti melalui javascript tepat sebelum pembukaan lapisan, Anda bisa secara dinamis menetapkan nilai itu sebagai topproperti elemen tubuh: dengan pendekatan ini halaman akan berdiri di tempatnya, tidak masalah jika Anda ' kembali di atas atau jika Anda sudah menggulir.

Css

.noscroll { position: fixed; overflow-y:scroll }

JS

$('body').css('top', -(document.documentElement.scrollTop) + 'px')
         .addClass('noscroll');
Fabrizio Calderan
sumber
2
itu mengacaukan tata letak saya tetapi dengan beberapa modifikasi itu hanya bisa berfungsi. Saya suka ini, saya akan mencobanya lebih banyak
Dejan.S
4
dengan sedikit modifikasi ini berfungsi. saya menambahkan lebar: 100%; saya pergi memperbarui pertanyaan saya dengan solusi tetapi Anda dapat memodifikasi dengan lebar: 100% ;? terima kasih untuk sarannya
Dejan.S
3
Saya tidak tahu mengapa, tetapi ini bekerja lebih baik untuk saya: $('body').css('top', -($('body').scrollTop()) + 'px').addClass('noscroll');
PDXIII
4
@ whitesiroi, kamu benar. Saya telah memperbarui biola: jsfiddle.net/evpozdniakov/2m8km9wg Terima kasih!
evpozdniakov
1
Bagi mereka yang membaca komentar untuk solusi, biola terakhir menyediakan solusi untuk menonaktifkan dan mengaktifkan kembali scrollbar sambil mempertahankan posisi scrollbar dalam kedua kasus. Terima kasih!
user1063287
78

Empat tambahan kecil untuk solusi yang dipilih:

  1. Terapkan 'noscroll' ke html alih-alih ke badan untuk mencegah bilah gulir ganda di IE
  2. Untuk memeriksa apakah sebenarnya ada bilah gulir sebelum menambahkan kelas 'noscroll'. Jika tidak, situs juga akan melompat didorong oleh bilah gulir non-gulir baru.
  3. Untuk menjaga kemungkinan scrollTop sehingga seluruh halaman tidak kembali ke atas (seperti pembaruan Fabrizio, tetapi Anda perlu mengambil nilainya sebelum menambahkan kelas 'noscroll')
  4. Tidak semua browser menangani scrollTop dengan cara yang sama seperti yang didokumentasikan di http://help.dottoro.com/ljnvjiow.php

Solusi lengkap yang tampaknya berfungsi untuk sebagian besar browser:

CSS

html.noscroll {
    position: fixed; 
    overflow-y: scroll;
    width: 100%;
}

Nonaktifkan gulir

if ($(document).height() > $(window).height()) {
     var scrollTop = ($('html').scrollTop()) ? $('html').scrollTop() : $('body').scrollTop(); // Works for Chrome, Firefox, IE...
     $('html').addClass('noscroll').css('top',-scrollTop);         
}

Aktifkan gulir

var scrollTop = parseInt($('html').css('top'));
$('html').removeClass('noscroll');
$('html,body').scrollTop(-scrollTop);

Terima kasih kepada Fabrizio dan Dejan karena menempatkan saya di jalur yang benar dan ke Brodingo untuk solusi bilah gulir ganda

Mike Garcia
sumber
1
Ini diuji dengan baik di desktop tetapi pada iPhone itu menciptakan layar putih kosong sampai pembaca berusaha untuk menggulir halaman. Setelah pembaca mencoba berinteraksi dengan halaman, layar yang dituju menjadi terlihat dengan gulir terkunci.
Michael Khalili
Ini berfungsi sempurna dengan Fancybox di iPad untuk menonaktifkan pengguliran gambar lightbox afterLoad()dan afterClosepanggilan balik. Dapat bermanfaat bagi orang lain yang mencari pertanyaan ini.
Tomanow
Di bagian "aktifkan gulir", Anda mungkin ingin menghapus atribut gaya yang ditempatkan pada elemen html setelah panggilan untuk "nonaktifkan gulir"; bukan?
Ben
3
jQuery membuat standar DOM asli scrollTopsehingga baris 2 dari kode 'Nonaktifkan gulir' dapat dinyatakan sebagai $( window ).scrollTop().
Barney
Saya pikir satu hal lain perlu ditambahkan ke ini. Pada Chrome di OSX, peramban mungkin "over-scroll", memberikan kesan elastis pada scrolling. Dengan kode ini jika Anda berada di area abu-abu di atas atau di bawah halaman dan Anda mengarahkan kursor ke tempat di mana Anda menonaktifkan pengguliran. Ini akan menempel pada tempat di atas / di bawah jendela browser. Untuk alasan ini Anda perlu menambahkan cek untuk nilai gulir negatif: if (scrollTop < 0) { scrollTop = 0; }. Berikut adalah kode lengkap untuk menonaktifkan gist.github.com/jayd3e/2eefbbc571cd1668544b .
JayD3e
34

Dengan jQuery yang disertakan:


nonaktifkan

$.fn.disableScroll = function() {
    window.oldScrollPos = $(window).scrollTop();

    $(window).on('scroll.scrolldisabler',function ( event ) {
       $(window).scrollTop( window.oldScrollPos );
       event.preventDefault();
    });
};

memungkinkan

$.fn.enableScroll = function() {
    $(window).off('scroll.scrolldisabler');
};

pemakaian

//disable
$("#selector").disableScroll();
//enable
$("#selector").enableScroll();
ceed
sumber
1
ini sempurna untuk saya, jawaban sebelumnya membuat halaman saya terpental, yang ini tidak
Bogdan Tomi
senang saya bisa membantu, Anda mungkin perlu memeriksa "touchmove" juga, untuk perangkat seluler, tepuk tangan
ceed
Yah, ini hampir berhasil untuk saya. Ini bekerja sangat baik pada Windows (Firefox, Chrome) dan MacOS di Firefox ... tapi kemudian saya pergi ke Windows IE dan Edge, bersama dengan MacOS di Chrome dan Safari. Masalahnya bukan lagi tentang halaman yang melompat dari sisi ke sisi, tetapi bilah gulir melompat dari atas ke posisi saat ini atau halaman berkedip-kedip di bagian atas. Sobat, ini sangat , sangat dekat. Mungkin kita masih bisa membuatnya bekerja.
Steven Ventimiglia
Ini bekerja dengan baik untuk saya, terima kasih! Ideal digunakan di situs web di mana menu overlay juga ada di bagian bawah halaman!
SauriolJf
12

Saya OP

Dengan bantuan jawaban dari fcalderan saya dapat membentuk solusi. Saya meninggalkan solusi saya di sini karena membawa kejelasan tentang cara menggunakannya, dan menambahkan detail yang sangat penting,width: 100%;

Saya menambahkan kelas ini

body.noscroll
{
    position: fixed; 
    overflow-y: scroll;
    width: 100%;
}

ini bekerja untuk saya dan saya menggunakan Fancyapp.

Dejan.S
sumber
11

Ini bekerja sangat baik untuk saya ....

// disable scrolling
$('body').bind('mousewheel touchmove', lockScroll);

// enable scrolling
$('body').unbind('mousewheel touchmove', lockScroll);


// lock window scrolling
function lockScroll(e) {
    e.preventDefault();
}

bungkus saja dua baris kode dengan apa pun yang memutuskan kapan Anda akan mengunci pengguliran.

misalnya

$('button').on('click', function() {
     $('body').bind('mousewheel touchmove', lockScroll);
});
dmackenz
sumber
Ini adalah jawaban terbaik dari semuanya
Jafo
7

Anda tidak dapat menonaktifkan acara gulir, tetapi Anda dapat menonaktifkan tindakan terkait yang mengarah ke gulir, seperti roda mouse dan roda sentuh:

$('body').on('mousewheel touchmove', function(e) {
      e.preventDefault();
});
tocqueville
sumber
4

Anda dapat menyembunyikan bilah gulir badan dengan overflow: hiddendan mengatur margin pada saat yang sama sehingga konten tidak melompat:

let marginRightPx = 0;
if(window.getComputedStyle) {
    let bodyStyle = window.getComputedStyle(document.body);
    if(bodyStyle) {
        marginRightPx = parseInt(bodyStyle.marginRight, 10);
    }
}

let scrollbarWidthPx = window.innerWidth - document.body.clientWidth;
Object.assign(document.body.style, {
    overflow: 'hidden',
    marginRight: `${marginRightPx + scrollbarWidthPx}px`
});

Dan kemudian Anda dapat menambahkan scrollbar yang dinonaktifkan ke halaman untuk mengisi celah:

textarea {
  overflow-y: scroll;
  overflow-x: hidden;
  width: 11px;
  outline: none;
  resize: none;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  border: 0;
}
<textarea></textarea>

Saya melakukan ini untuk implementasi lightbox saya sendiri. Tampaknya bekerja dengan baik sejauh ini.

Mpen
sumber
1
Saya sebenarnya suka metode ini yang terbaik. Sangat sederhana dan bekerja dengan sangat baik. Terima kasih!
dericcain
2

Ini adalah solusi yang kami gunakan. Cukup simpan posisi gulir saat hamparan dibuka, gulir kembali ke posisi simpanan setiap kali pengguna mencoba menggulir halaman, dan matikan pendengar saat hamparan ditutup.

Ini agak gelisah di IE, tetapi bekerja seperti pesona di Firefox / Chrome.

var body = $("body"),
  overlay = $("#overlay"),
  overlayShown = false,
  overlayScrollListener = null,
  overlaySavedScrollTop = 0,
  overlaySavedScrollLeft = 0;

function showOverlay() {
  overlayShown = true;

  // Show overlay
  overlay.addClass("overlay-shown");

  // Save scroll position
  overlaySavedScrollTop = body.scrollTop();
  overlaySavedScrollLeft = body.scrollLeft();

  // Listen for scroll event
  overlayScrollListener = body.scroll(function() {
    // Scroll back to saved position
    body.scrollTop(overlaySavedScrollTop);
    body.scrollLeft(overlaySavedScrollLeft);
  });
}

function hideOverlay() {
  overlayShown = false;

  // Hide overlay
  overlay.removeClass("overlay-shown");

  // Turn scroll listener off
  if (overlayScrollListener) {
    overlayScrollListener.off();
    overlayScrollListener = null;
  }
}

// Click toggles overlay
$(window).click(function() {
  if (!overlayShown) {
    showOverlay();
  } else {
    hideOverlay();
  }
});
/* Required */
html, body { margin: 0; padding: 0; height: 100%; background: #fff; }
html { overflow: hidden; }
body { overflow-y: scroll; }

/* Just for looks */
.spacer { height: 300%; background: orange; background: linear-gradient(#ff0, #f0f); }
.overlay { position: fixed; top: 20px; bottom: 20px; left: 20px; right: 20px; z-index: -1; background: #fff; box-shadow: 0 0 5px rgba(0, 0, 0, .3); overflow: auto; }
.overlay .spacer { background: linear-gradient(#88f, #0ff); }
.overlay-shown { z-index: 1; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<h1>Top of page</h1>
<p>Click to toggle overlay. (This is only scrollable when overlay is <em>not</em> open.)</p>
<div class="spacer"></div>
<h1>Bottom of page</h1>
<div id="overlay" class="overlay">
  <h1>Top of overlay</h1>
  <p>Click to toggle overlay. (Containing page is no longer scrollable, but this is.)</p>
  <div class="spacer"></div>
  <h1>Bottom of overlay</h1>
</div>

0b10011
sumber
Memang berfungsi, tetapi mencemari desain jika header tetap, saat scrollbar menyelam di bawahnya.
Leon Willens
@LeonWillens Saya tidak yakin apa yang Anda maksud. Jika Anda khawatir tentang overlay muncul di bawah header tetap, Anda akan perlu menyesuaikan z-indexdari .overlay-shownlebih besar dari header tetap. (Saya memiliki kode ini berjalan dalam produksi di situs dengan tajuk yang tetap dan berfungsi dengan baik.)
0b10011
Tidak, saya berbicara tentang bilah gulir bodytag. Saya bereksperimen dengan kode Anda kemarin dan saya memiliki tajuk yang tetap di bagian atas halaman saya. Jika saya menangani pengguliran melalui bodytag, scrollbar akan berada di bawah header tetap.
Leon Willens
1
@LeonWillens Ups, sepertinya saya memperbaiki ini dalam produksi di beberapa titik dan lupa untuk memperbarui ini. Sepertinya alih-alih $("body"), kami menggunakan $(window). Dan alih-alih z-index: -1pada hamparan untuk menyembunyikannya, Anda dapat menggunakan visibility: hiddenatau serupa. Lihat jsfiddle.net/8p2gfeha untuk tes cepat untuk melihat apakah itu berhasil. Header tetap tidak lagi muncul di atas scrollbar. Saya akhirnya akan mencoba memasukkan perubahan ini ke dalam jawabannya.
0b10011
Bekerja seperti pesona! Terima kasih :)
Leon Willens
1

Saya memiliki masalah yang sama: menu sebelah kiri yang, ketika muncul, mencegah bergulir. Begitu ketinggian diatur ke 100vh, bilah gulir menghilang dan konten tersentak ke kanan.

Jadi, jika Anda tidak keberatan mengaktifkan bilah gulir (tetapi mengatur jendela ke ketinggian penuh sehingga tidak akan benar-benar menggulir ke mana pun) maka kemungkinan lain adalah mengatur margin bawah yang kecil, yang akan membuat bilah gulir ditampilkan:

body {
    height: 100vh;
    overflow: hidden;
    margin: 0 0 1px;
}
dhc
sumber
Tidakkah hal itu overflow:hiddenmencegah margin dari pengaruhnya?
Koja
0

Anda dapat terus meluap: disembunyikan tetapi mengelola posisi gulir secara manual:

sebelum menampilkan jejak gulir posisi aktual:

var scroll = [$(document).scrollTop(),$(document).scrollLeft()];
//show your lightbox and then reapply scroll position
$(document).scrollTop(scroll[0]).scrollLeft(scroll[1]);

itu harus bekerja

malko
sumber
0

Cara kasar tetapi berfungsi adalah memaksa gulungan kembali ke atas, sehingga secara efektif menonaktifkan pengguliran:

var _stopScroll = false;
window.onload = function(event) {
    document.onscroll = function(ev) {
        if (_stopScroll) {
            document.body.scrollTop = "0px";
        }
    }
};

Saat Anda membuka lightbox, angkat bendera dan saat menutupnya, turunkan bendera.

Kasing uji langsung .

Shadow Wizard adalah Telinga Untuk Anda
sumber
0

Saya suka tetap menggunakan metode "overflow: hidden" dan hanya menambahkan padding-right yang sama dengan lebar scrollbar.

Dapatkan fungsi lebar scrollbar, dengan sumber hilang .

function getScrollbarWidth() {
    var outer = document.createElement("div");
    outer.style.visibility = "hidden";
    outer.style.width = "100px";
    outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps

    document.body.appendChild(outer);

    var widthNoScroll = outer.offsetWidth;
    // force scrollbars
    outer.style.overflow = "scroll";

    // add innerdiv
    var inner = document.createElement("div");
    inner.style.width = "100%";
    outer.appendChild(inner);        

    var widthWithScroll = inner.offsetWidth;

    // remove divs
    outer.parentNode.removeChild(outer);

    return widthNoScroll - widthWithScroll;
}

Saat menampilkan overlay, tambahkan kelas "noscroll" ke html dan tambahkan padding-right ke body:

$(html).addClass("noscroll");
$(body).css("paddingRight", getScrollbarWidth() + "px");

Saat bersembunyi, lepaskan kelas dan padding:

$(html).removeClass("noscroll");
$(body).css("paddingRight", 0);

Gaya noscroll hanya ini:

.noscroll { overflow: hidden; }

Perhatikan bahwa jika Anda memiliki elemen dengan posisi: diperbaiki, Anda perlu menambahkan padding ke elemen-elemen itu juga.

Janne Annala
sumber
Saya menggunakan solusi ini. Ini membantu saya untuk menghindari bilah gulir ganda (satu 'kosong' untuk tubuh dan yang kedua untuk isi overlay). Ini juga bekerja dengan sangat baik pada OSX yang mungkin atau mungkin tidak menampilkan scrollbar sama sekali.
Novazembla
0

<div id="lightbox">ada di dalam <body>elemen, jadi ketika Anda menggulir lightbox Anda juga menggulir tubuh. Solusinya adalah untuk tidak memperpanjang <body>elemen lebih dari 100%, untuk menempatkan konten lama di dalam divelemen lain dan menambahkan scrollbar jika diperlukan dengan divelemen ini overflow: auto.

html {
  height: 100%
}
body {
  margin: 0;
  height: 100%
}
#content {
  height: 100%;
  overflow: auto;
}
#lightbox {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
<html>
  <body>
    <div id="content">much content</div>
    <div id="lightbox">lightbox<div>
  </body>
</html>

Sekarang, menggulir kotak cahaya (dan bodyjuga) tidak memiliki efek, karena bodi tidak lebih dari 100% dari tinggi layar.

Marek C
sumber
0

Semua sistem berbasis modal / lightbox javascript menggunakan overflow saat menampilkan modal / lightbox, pada tag html atau tag tubuh.

Saat lightbox ditampilkan, js mendorong limpahan yang disembunyikan pada html atau tag tubuh. Ketika lightbox disembunyikan, beberapa menghapus yang tersembunyi lainnya mendorong auto overflow pada html atau tag tubuh.

Pengembang yang bekerja di Mac, tidak melihat masalah scrollbar.

Ganti saja yang disembunyikan dengan yang tidak disetel untuk tidak melihat konten yang tergelincir di bawah modal penghapusan scrollbar.

Lightbox terbuka / tampilkan:

<html style="overflow: unset;"></html>

Tutup / sembunyikan Lightbox:

<html style="overflow: auto;"></html>
Kedok
sumber
0

Jika halaman di bawah overlayer dapat "diperbaiki" di bagian atas, saat Anda membuka overlay yang dapat Anda atur

.disableScroll { position: fixed; overflow-y:scroll }

berikan kelas ini ke badan yang dapat digulir, Anda masih harus melihat bilah gulir kanan tetapi kontennya tidak dapat digulir.

Untuk mempertahankan posisi halaman lakukan ini dalam jquery

$('body').css('top', - ($(window).scrollTop()) + 'px').addClass('disableScroll');

Saat Anda menutup overlay, kembalikan properti ini dengan

var top = $('body').position().top;
$('body').removeClass('disableScroll').css('top', 0).scrollTop(Math.abs(top));

Saya hanya mengusulkan cara ini hanya karena Anda tidak perlu mengubah acara gulir

Bhuvan Arora
sumber
0

Ini akan menghentikan viewport melompat ke atas dengan menyimpan posisi gulir dan mengembalikannya pada mengaktifkan gulir.

CSS

.no-scroll{
  position: fixed; 
  width:100%;
  min-height:100vh;
  top:0;
  left:0;
  overflow-y:scroll!important;
}

JS

var scrollTopPostion = 0;

function scroll_pause(){
  scrollTopPostion = $(window).scrollTop();
  $("body").addClass("no-scroll").css({"top":-1*scrollTopPostion+"px"});
}

function scroll_resume(){
  $("body").removeClass("no-scroll").removeAttr("style");
  $(window).scrollTop(scrollTopPostion);
}

Sekarang yang perlu Anda lakukan adalah memanggil fungsi

$(document).on("click","#DISABLEelementID",function(){
   scroll_pause();
});

$(document).on("click","#ENABLEelementID",function(){
   scroll_resume();
});
Kareem
sumber
-1

Anda dapat melakukannya dengan Javascript:

// Classic JS
window.onscroll = function(ev) {
  ev.preventDefault();
}

// jQuery
$(window).scroll(function(ev) {
  ev.preventDefault();
}

Dan kemudian nonaktifkan ketika lightbox Anda ditutup.

Tetapi jika lightbox Anda berisi bilah gulir, Anda tidak akan dapat menggulir saat itu terbuka. Ini karena windowmengandung keduanya bodydan #lightbox. Jadi, Anda harus menggunakan arsitektur seperti yang berikut:

<body>
  <div id="global"></div>
  <div id="lightbox"></div>
</body>

Dan kemudian terapkan onscrollacara hanya pada #global.

Sama saja
sumber