Deteksi apakah halaman memiliki scrollbar vertikal?


121

Saya hanya ingin beberapa JQ / JS sederhana untuk memeriksa apakah halaman / jendela saat ini (bukan elemen tertentu) memiliki scrollbar vertikal.

Googling memberi saya hal-hal yang tampaknya terlalu rumit hanya untuk fitur dasar ini.

Bagaimana ini bisa dilakukan?

Jawaban:


97
$(document).ready(function() {
    // Check if body height is higher than window height :)
    if ($("body").height() > $(window).height()) {
        alert("Vertical Scrollbar! D:");
    }

    // Check if body width is higher than window width :)
    if ($("body").width() > $(window).width()) {
        alert("Horizontal Scrollbar! D:<");
    }
});

14
+1 tetapi demi ketepatan, ini hanya memeriksa apakah konten meluas lebih jauh dari viewport. Jika overflowproperti dari bodydisetel ke hiddensuatu tempat di sepanjang garis, itu tidak akan berfungsi. Pengaturan tersembunyi pada tubuh sangat jarang.
Pekka

4
Ini tidak berfungsi jika tinggi badan sama dengan tinggi jendela, yang terjadi jika tinggi dokumen sama persis dengan area pandang, maka bilah gulir horizontal ditambahkan . Ini akan memaksa vert. scrollbar tetapi tinggi doc / body / window sama; itu TIDAK akan mengingatkan "scrollbar vertikal" bahkan jika ada.
Berhenti Memfitnah Monica Cellio

2
Hanya berpikir saya akan menyebutkan bahwa saya harus menggunakan $(document)alih-alih $("body"), ini berfungsi untuk saya ketika tubuh tidak (saya memiliki wadah yang diposisikan absolut dengan rasio aspek lebar / tinggi)
am_

1
Saya memiliki halaman laporan di browser Chrome yang awalnya menampilkan bilah gulir dan menghilang dalam hitungan milidetik yang terlihat seperti perilaku browser karena saya tidak memprogramnya. Jadi fungsi ini selalu mengembalikan nilai true dalam kasus saya ..
Dush

@TiuTalk untuk saya $ ("body"). Height () & $ (window) .height () memberikan nilai yang sama, sebagai gantinya saya menggunakan $ (document) .height ()> $ (window) .height () itu berfungsi untuk saya.
SarangK

77

coba ini:

var hasVScroll = document.body.scrollHeight > document.body.clientHeight;

Namun, ini hanya akan memberi tahu Anda jika scrollHeight vertikal lebih besar dari tinggi konten yang dapat dilihat. The hasVScrollvariabel akan berisi benar atau salah.

Jika Anda perlu melakukan pemeriksaan yang lebih menyeluruh, tambahkan yang berikut ini ke kode di atas:

// Get the computed style of the body element
var cStyle = document.body.currentStyle||window.getComputedStyle(document.body, "");

// Check the overflow and overflowY properties for "auto" and "visible" values
hasVScroll = cStyle.overflow == "visible" 
             || cStyle.overflowY == "visible"
             || (hasVScroll && cStyle.overflow == "auto")
             || (hasVScroll && cStyle.overflowY == "auto");

1
+1 Bagus! Dan dengan gaya komputasi yang diperlukan (yang merupakan titik di mana saya memutuskan untuk tidak terlibat dengan pertanyaan ini;)
Pekka

lol ya saya sedang berdebat apakah harus melakukan upaya ekstra untuk menulisnya atau tidak karena dalam banyak kasus hal itu tidak diperlukan.
Andy E

1
Ini menghasilkan hasVScroll menjadi true setiap kali overflowY 'terlihat' terlepas dari apakah scrollHeight lebih besar dari clientHeight. Mungkin maksudmu cStyle.overflow === 'scroll'?
BT

5
Kode di atas tidak berfungsi. Browser: Chrome 56. Url: news.greylock.com/…
Sebastien Lorber

1
@BT cStyle.overflow == "visible" dapat menampilkan bilah gulir jika elemennya adalah document.body. Tetapi harus (hasVScroll && cStyle.overflow == "visible" && element.nodeName == "BODY"). Selain itu, perlu diperiksa cStyle.overflow === 'scroll'seperti yang Anda tunjukkan.
mseifert

44

Saya mencoba jawaban sebelumnya dan tampaknya tidak berhasil, $ ("body"). Height () tidak selalu mewakili tinggi html secara keseluruhan.

Saya telah mengoreksi solusinya sebagai berikut:

// Check if body height is higher than window height :) 
if ($(document).height() > $(window).height()) { 
    alert("Vertical Scrollbar! D:"); 
} 

// Check if body width is higher than window width :) 
if ($(document).width() > $(window).width()) { 
    alert("Horizontal Scrollbar! D:<"); 
} 

18

Mari kita kembalikan pertanyaan ini dari kematian;) Ada alasan mengapa Google tidak memberi Anda solusi sederhana. Kasus khusus dan kebiasaan browser memengaruhi penghitungan, dan ini tidak semudah yang terlihat.

Sayangnya, sejauh ini ada masalah dengan solusi yang diuraikan di sini. Saya tidak bermaksud untuk meremehkan mereka sama sekali - mereka adalah titik awal yang bagus dan menyentuh semua properti utama yang diperlukan untuk pendekatan yang lebih kuat. Tetapi saya tidak akan merekomendasikan untuk menyalin dan menempelkan kode dari jawaban lain karena

  • mereka tidak menangkap efek konten yang diposisikan dengan cara yang dapat diandalkan lintas-browser. Jawaban yang didasarkan pada ukuran tubuh melewatkan ini sepenuhnya (tubuh tidak offset induk dari konten tersebut kecuali jika diposisikan sendiri). Dan jawaban itu memeriksa $( document ).width()dan .height()menjadi mangsa deteksi buggy jQuery tentang ukuran dokumen .
  • Mengandalkan window.innerWidth, jika browser mendukungnya, membuat kode Anda gagal mendeteksi bilah gulir di peramban seluler, yang umumnya lebar bilah gulir 0. Mereka hanya ditampilkan sementara sebagai hamparan dan tidak memakan ruang di dokumen . Melakukan zoom pada ponsel juga menjadi masalah (cerita panjang).
  • Deteksi dapat dilakukan ketika orang secara eksplisit mengatur luapan elemen htmldan bodyke nilai non-default (yang terjadi kemudian adalah sedikit terlibat - lihat deskripsi ini ).
  • Dalam kebanyakan jawaban, body padding, border atau margin tidak terdeteksi dan mengubah hasil.

Saya telah menghabiskan lebih banyak waktu daripada yang saya bayangkan untuk menemukan solusi yang "langsung bekerja" (batuk). Algoritma yang saya buat sekarang menjadi bagian dari plugin, jQuery.isInView , yang mengekspos sebuah .hasScrollbarmetode . Lihat sumbernya jika Anda mau.

Dalam skenario di mana Anda memiliki kendali penuh atas halaman dan tidak harus berurusan dengan CSS yang tidak dikenal, menggunakan plugin mungkin berlebihan - lagipula, Anda tahu kasus edge mana yang berlaku, dan mana yang tidak. Namun, jika Anda memerlukan hasil yang andal di lingkungan yang tidak diketahui, saya rasa solusi yang diuraikan di sini tidak akan cukup. Anda lebih baik menggunakan plugin yang telah teruji - milik saya atau orang lain.


Terima kasih. Agak rumit! Jika Anda tidak ingin / perlu kompatibel ke belakang, apakah mungkin ada solusi yang lebih mudah untuk browser html5? Maksud saya, mungkin pembuat kode browser / w3c sudah cukup baik untuk memberi tahu kami apakah ada bilah gulir atau tidak pada suatu elemen? ;-)
Leo

1
@ Leo Bukan yang saya sadari. Nah, ada sebuah window.scrollbarsobjek yang memiliki satu properti , visible. Kedengarannya menjanjikan tetapi tidak. Itu tidak didukung di IE, termasuk IE11. Dan itu hanya memberitahu Anda bahwa ada sebuah scroll bar - tetapi tidak yang mana. Lihat halaman pengujian di sini .
hashchange

Terima kasih @hashchange. Kedengarannya sangat bodoh karena hanya memberi tahu apakah ada scrollbar jadi saya kira ini hanya semacam tes. Agak menjanjikan. ;-)
Leo

1
@BT Ok, bagus. Sekarang izinkan saya membawa Anda ke pintu masuk lubang kelinci;) Berikut adalah demo di mana isinya tidak cukup untuk mengisi jendela. Deteksi Anda berfungsi di FF tetapi gagal di Chrome. Dan inilah demo lain di mana elemen yang diposisikan ditempatkan jauh di bawah halaman. Deteksi Anda berfungsi di Chrome tetapi gagal di FF.
hashchange

1
@BT Dan saya kira kita bisa masuk ke sekumpulan mode kegagalan aneh ketika kita mulai bermain dengan pengaturan overflow karena perilakunya sedikit aneh , tapi saya sudah berhenti di situ.
hashchange

15

Yang ini berhasil untuk saya:

function hasVerticalScroll(node){
    if(node == undefined){
        if(window.innerHeight){
            return document.body.offsetHeight> window.innerHeight;
        }
        else {
            return  document.documentElement.scrollHeight > 
                document.documentElement.offsetHeight ||
                document.body.scrollHeight>document.body.offsetHeight;
        }
    }
    else {
        return node.scrollHeight> node.offsetHeight;
    }
}

Untuk bodi, pakai saja hasVerticalScroll().


Ini adalah satu-satunya jawaban di utas ini yang berfungsi di Chrome saya
Nertan Lucian

clientHeightlebih disukai di offsetHeightsini. Jika tidak, Anda dapat memiliki batas tebal, dan mengembalikan tidak ada bilah gulir saat ada.
theicfire


3

Anehnya, tidak ada solusi ini yang memberi tahu Anda jika halaman memiliki scrollbar vertikal.

window.innerWidth - document.body.clientWidthakan memberi Anda lebar scrollbar. Ini harus bekerja di IE9 + apa pun (tidak diuji di browser yang lebih rendah). (Atau untuk menjawab pertanyaan dengan tegas,!!(window.innerWidth - document.body.clientWidth)

Mengapa? Misalkan Anda memiliki halaman di mana konten lebih tinggi dari tinggi jendela dan pengguna dapat menggulir ke atas / bawah. Jika Anda menggunakan Chrome di Mac tanpa tetikus yang terpasang, pengguna tidak akan melihat bilah gulir. Colokkan mouse dan scrollbar akan muncul. (Perhatikan perilaku ini dapat diganti, tapi itulah AFAIK default).


Penjelasan tentang perilaku Chrome-Mouse membantu saya mengetahui apa yang menurut saya merupakan perilaku yang tidak konsisten. Terima kasih!
theisof

2

Saya menemukan solusi vanila

var hasScrollbar = function() {
  // The Modern solution
  if (typeof window.innerWidth === 'number')
    return window.innerWidth > document.documentElement.clientWidth

  // rootElem for quirksmode
  var rootElem = document.documentElement || document.body

  // Check overflow style property on body for fauxscrollbars
  var overflowStyle

  if (typeof rootElem.currentStyle !== 'undefined')
    overflowStyle = rootElem.currentStyle.overflow

  overflowStyle = overflowStyle || window.getComputedStyle(rootElem, '').overflow

    // Also need to check the Y axis overflow
  var overflowYStyle

  if (typeof rootElem.currentStyle !== 'undefined')
    overflowYStyle = rootElem.currentStyle.overflowY

  overflowYStyle = overflowYStyle || window.getComputedStyle(rootElem, '').overflowY

  var contentOverflows = rootElem.scrollHeight > rootElem.clientHeight
  var overflowShown    = /^(visible|auto)$/.test(overflowStyle) || /^(visible|auto)$/.test(overflowYStyle)
  var alwaysShowScroll = overflowStyle === 'scroll' || overflowYStyle === 'scroll'

  return (contentOverflows && overflowShown) || (alwaysShowScroll)
}


1
Tidak berfungsi di IE 11. window.innerWidth & document.documentElement.clientWidth selalu sama.
NLV

Diperbaiki. Fungsi yang sama ini juga berfungsi untuk IE 11. Masalahnya adalah ini - stackoverflow.com/questions/17045132/…
NLV

Saya menguji ini di Chrome 65 dan berhasil. Tetapi ketika saya menyesuaikannya untuk scrollbar horizontal, hasilnya aneh: Jika scrollbar horizontal dan vertikal ditampilkan, window.innerWidth > document.documentElement.clientWidthitu benar, tetapi window.innerHeight > document.documentElement.clientHeighttidak. Sepertinya yang terjadi dalam kasus ini adalah sebaliknya. Saya bukan pengembang JS, saya hanya membutuhkannya untuk tes Selenium. Saya berterima kasih atas petunjuk.
kriegaex

2
    <script>
    var scrollHeight = document.body.scrollHeight;
    var clientHeight = document.documentElement.clientHeight;
    var hasVerticalScrollbar = scrollHeight > clientHeight;

    alert(scrollHeight + " and " + clientHeight); //for checking / debugging.
    alert("hasVerticalScrollbar is " + hasVerticalScrollbar + "."); //for checking / debugging.
    </script>

Yang ini akan memberi tahu Anda apakah Anda memiliki scrollbar atau tidak. Saya telah menyertakan beberapa informasi yang dapat membantu debugging, yang akan ditampilkan sebagai peringatan JavaScript.

Letakkan ini di tag skrip, setelah tag body penutup.


1

Saya menulis versi terbaru dari jawaban Kees C.Bakker:

const hasVerticalScroll = (node) => {
  if (!node) {
    if (window.innerHeight) {
      return document.body.offsetHeight > window.innerHeight
    }
    return (document.documentElement.scrollHeight > document.documentElement.offsetHeight)
      || (document.body.scrollHeight > document.body.offsetHeight)
  }
  return node.scrollHeight > node.offsetHeight
}

if (hasVerticalScroll(document.querySelector('body'))) {
  this.props.handleDisableDownScrollerButton()
}

Fungsi mengembalikan true atau false tergantung apakah halaman memiliki scrollbar vertikal atau tidak.

Sebagai contoh:

const hasVScroll = hasVerticalScroll(document.querySelector('body'))

if (hasVScroll) {
  console.log('HAS SCROLL', hasVScroll)
}

1

saya menggunakan

public windowHasScroll()
{
    return document.body.clientHeight > document.documentElement.clientHeight;
}

1

Cukup bandingkan lebar elemen root dokumen (yaitu elemen html) dengan bagian dalam jendela:

if ((window.innerWidth - document.documentElement.clientWidth) >0) console.log('V-scrollbar active')

Jika Anda juga perlu mengetahui lebar scrollbar:

vScrollbarWidth = window.innerWidth - document.documentElement.clientWidth;

0

Solusi lain tidak berfungsi di salah satu proyek saya dan saya akhirnya memeriksa properti overflow css

function haveScrollbar() {
    var style = window.getComputedStyle(document.body);
    return style["overflow-y"] != "hidden";
}

tetapi hanya akan berfungsi jika scrollbar muncul menghilang dengan mengubah prop itu tidak akan berfungsi jika konten sama atau lebih kecil dari jendela.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.