Periksa apakah elemen HTML memiliki scrollbar

113

Apa cara tercepat untuk memeriksa apakah suatu elemen memiliki bilah gulir?

Satu hal tentu saja adalah memeriksa apakah elemen lebih besar dari viewport-nya, yang dapat dengan mudah dilakukan dengan memeriksa dua nilai berikut:

el.scrollHeight > el.offsetHeight || el.scrollWidth > el.offsetWidth

tetapi itu tidak berarti bahwa ia juga memiliki scrollbar (jadi itu sebenarnya dapat di-scroll oleh manusia).

Pertanyaan

Bagaimana cara memeriksa scrollbar dalam 1 browser silang dan 2 javascript saja (seperti tidak ada jQuery )?

Hanya Javascript, karena saya memerlukan overhead sekecil mungkin, karena saya ingin menulis filter pemilih jQuery yang sangat cepat

// check for specific scrollbars
$(":scrollable(x/y/both)")

// check for ANY scrollbar
$(":scrollable")

Saya kira saya harus memeriksa overflowpengaturan gaya tetapi bagaimana saya melakukannya dengan cara lintas browser?

Pengeditan tambahan

Tidak hanya overflowpengaturan gaya. Memeriksa apakah suatu elemen memiliki scrollbar tidak sesederhana kelihatannya. Rumus pertama yang saya tulis di atas berfungsi dengan baik ketika elemen tidak memiliki perbatasan, tetapi ketika itu terjadi (terutama ketika perbatasan memiliki lebar yang cukup), offsetdimensi bisa lebih besar dari scrolldimensi tetapi elemen masih bisa digulir. Kami sebenarnya harus mengurangi batas dari offsetdimensi untuk mendapatkan viewport aktual yang dapat digulir dari elemen dan membandingkannya dengan scrolldimensi.

Untuk referensi di masa mendatang

:scrollableFilter pemilih jQuery disertakan dalam .scrollintoview()plugin jQuery saya . Kode lengkap dapat ditemukan di posting blog saya jika ada yang membutuhkannya. Meskipun tidak memberikan solusi sebenarnya, kode Soumya sangat membantu saya menyelesaikan masalah. Ini mengarahkan saya ke arah yang benar.

Robert Koritnik
sumber

Jawaban:

118

Saya menemukan ini di suatu tempat beberapa minggu yang lalu. Itu berhasil untuk saya.

var div = document.getElementById('container_div_id');

var hasHorizontalScrollbar = div.scrollWidth > div.clientWidth;
var hasVerticalScrollbar = div.scrollHeight > div.clientHeight;

/* you'll get true/false */
jzhinga.dll
sumber
12
Anda jelas memiliki contoh yang disederhanakan. Bagaimana jika wadah Anda sudah overflow:hiddenterpasang di atasnya? Akan ada konten berlebih tetapi masih tidak dapat di-scroll. Masalahnya sejauh ini tidak sesederhana kelihatannya.
Robert Koritnik
7
Ini mungkin bukan solusi yang diterima, tetapi berhasil untuk saya. Saya tidak yakin mengapa Anda menggulirnya jika tersembunyi.
vol7ron
Ini mungkin bukan solusi yang diterima, tetapi berhasil untuk saya. Robert, untuk kasus tersebut, tidak bisakah Anda juga mengambil properti css overflow untuk menguji kasus tersebut (misalnya div.scrollHeight>div.clientHeight && !(div.style.overflow && div.style.overflow == 'hidden'))?
vol7ron
7
Ini gagal dalam banyak kasus. Jika elemen Anda memiliki luapan: terlihat; lebar: 200px; dan memiliki anak dengan lebar 500px, elemen Anda tidak memiliki scroll bar tetapi memiliki scrollWidth 500px dan clientWidth 200px.
Joseph Lennox
1
Jika overflow terlihat atau disembunyikan, biasanya tidak ada scrollbar.
Hubert Grzeskowiak
16

Mencoba:

Untuk scroll bar vertikal

el.scrollHeight> el.clientHeight

Untuk scrollbar horizontal

el.scrollWidth> el.clientWidth

Saya tahu ini berfungsi setidaknya untuk IE8 dan Firefox 3.6+.

Gary
sumber
2
Saya menunjukkan ini ya bahwa ini memberi tahu saya bahwa elemen tertentu lebih besar dari yang terlihat, tetapi itu tidak berarti itu menampilkan scrollbar. Itu juga bisa overflow:hiddendan tidak akan bisa digulir lagi.
Robert Koritnik
1
Dan memeriksa dengan nilai clientHeight / clientWidth tidak memberikan hasil yang baik, karena elemen juga dapat memiliki batas, yang tidak termasuk dalam pengukuran ini. Periksa formula saya. Ini bekerja lebih baik dari milik Anda.
Robert Koritnik
Itu benar tentang penggunaan offsetHeight / offsetWidth untuk memeriksa scrollbar daripada clientHeight / clientWidth. Terima kasih telah menunjukkannya.
Gary
@RobertKoritnik - jadi periksa saja apakah ada elemen tertentu overflow:hiddendi dalamnya ... ini masih jawaban yang benar menurut saya, karena ini yang paling sederhana.
vsync
14

Ini mungkin tampak (atau menjadi) sedikit hackish, tetapi Anda dapat menguji properti scrollTopdan scrollLeft.

Jika lebih besar dari 0, Anda tahu ada scrollbar. Jika nilainya 0, setel ke 1, dan uji lagi untuk melihat apakah Anda mendapatkan hasil 1. Kemudian setel kembali ke 0.

Contoh: http://jsfiddle.net/MxpR6/1/

function hasScroll(el, direction) {
    direction = (direction === 'vertical') ? 'scrollTop' : 'scrollLeft';
    var result = !! el[direction];

    if (!result) {
        el[direction] = 1;
        result = !!el[direction];
        el[direction] = 0;
    }
    return result;
}

alert('vertical? ' + hasScroll(document.body, 'vertical'));
alert('horizontal? ' + hasScroll(document.body, 'horizontal'));

Saya yakin ada properti yang berbeda untuk IE, jadi saya akan memperbaruinya sebentar lagi.

EDIT: Muncul seolah-olah IE mungkin mendukung properti ini. (Saya tidak dapat menguji IE sekarang.)

http://msdn.microsoft.com/en-us/library/ms534618(VS.85).aspx

pengguna113716
sumber
Jauh lebih mudah untuk memeriksa scrollbar jika Anda membandingkan offsetHeightdan clientHeight. Yang terakhir ini selalu lebih kecil dari ukuran scrollbar saat scrollbar ada.
Robert Koritnik
@Robert: Tidak yakin tentang lebih mudah, tapi saya melihat cara kerjanya. Kemudian saya berasumsi jika sebuah elemen memiliki overflow:scroll, Anda ingin itu dilaporkan sebagai scrollable apakah scrollbar diaktifkan atau tidak. Tentu saja solusi saya bisa bermasalah jika ada acara onscroll yang dilampirkan.
pengguna113716
Tidak juga. Jika Anda memeriksa plugin jQuery saya, saya harus menemukan leluhur aktual yang dapat digulir, jika tidak, saya tidak dapat menggulir elemen ke dalam tampilan.
Robert Koritnik
8
@Robertornik Tidak benar; beberapa browser mungkin memiliki scrollbar yang tidak mengurangi lebarnya. Di OS X misalnya. Atau perangkat sentuh.
daniel.gindi
1
selalu kembali salah
Fatih Erol
14

Ini solusi lainnya:

Seperti yang ditunjukkan oleh beberapa orang, membandingkan offsetHeight dan scrollHeight saja tidak cukup karena keduanya berbeda pada elemen dengan overflow hidden, dll., Yang masih tidak memiliki scrollbar. Jadi di sini saya juga memeriksa apakah overflow adalah scroll atau otomatis pada gaya yang dihitung untuk elemen tersebut:

var isScrollable = function(node) {
  var overflowY = window.getComputedStyle(node)['overflow-y'];
  var overflowX = window.getComputedStyle(node)['overflow-x'];
  return {
    vertical: (overflowY === 'scroll' || overflowY === 'auto') && node.scrollHeight > node.clientHeight,
    horizontal: (overflowX === 'scroll' || overflowX === 'auto') && node.scrollWidth > node.clientWidth,
  };
}
lotif
sumber
Jika overflow*ini scrollakan selalu ada scrollbar, jadi saya pikir Anda ingin vertical: overflowY === 'scroll' || overflowY === 'auto' && node.scrollHeight > node.clientHeight, dll (yaitu menghapus kurung sehingga scroll*vs client*hanya diuji ketika overflow*adalah auto). Jika tidak, ini tampaknya solusi yang paling tepat.
Jake
@Jake Jika scrollHeight <clientHeight pada scroll overflow, scrollbar akan ada di sana tetapi akan dinonaktifkan (yaitu elemen tidak dapat di-scroll). Jadi menurut saya itu tergantung aplikasinya. Modifikasi Anda berlaku jika Anda hanya ingin memeriksa scrollbar, tidak peduli statusnya. Bagi saya, ketika saya datang dengan ini, saya ingin mengimplementasikan autoscroll untuk sebuah komponen, jadi memiliki scrollbar yang dinonaktifkan tidak berguna dalam kasus itu. Itu juga tampaknya menjadi kasus untuk pertanyaan ini (ini perlu "digulir oleh manusia")
lotif
6

Saya mungkin sedikit terlambat ke pesta, tapi ...

Saya yakin Anda dapat mendeteksi scrollbar dengan e.offsetWidth vs. e.clientWidth. Lebar offset termasuk batas dan bilah gulir, bantalan dan lebar. Lebar klien termasuk bantalan dan lebar. Silahkan lihat:

https://developer.mozilla.org/en/DOM/element.offsetWidth (gambar kedua) https://developer.mozilla.org/en/DOM/element.clientWidth (gambar kedua)

Anda perlu memeriksa:

  1. Apakah elemen memiliki overflow disetel ke auto / scroll (termasuk overflowX / Y) menggunakan gaya computed / cascaded / current.
  2. Jika elemen memiliki overflow yang disetel ke auto / scroll. Tetapkan offsetWidth dan clientWidth.
  3. Jika clientWidth kurang dari batas kanan offsetWidth (ditemukan lagi melalui gaya computed / cascaded / current), maka Anda tahu bahwa Anda memiliki scrollbar.

Lakukan hal yang sama untuk vertikal (offset / clientHeight).

IE7 melaporkan clientHeight 0 untuk beberapa elemen (saya belum memeriksa mengapa), oleh karena itu Anda selalu memerlukan pemeriksaan overflow pertama.

Semoga ini membantu!


sumber
3

Ada beberapa masalah dalam hal memeriksa keberadaan scrollbar salah satunya adalah di mac Anda tidak memiliki scrollbar yang terlihat sehingga kedua solusi di atas tidak akan memberi Anda jawaban yang akurat.

Jadi karena rendering browser tidak terlalu sering, Anda dapat memeriksa scrolling dengan mengubah scroll dan kemudian mengaturnya kembali:

const hasScrollBar = (element) => {
  const {scrollTop} = element;

  if(scrollTop > 0) {
    return true;
  }

  element.scrollTop += 10;

  if(scrollTop === element.scrollTop) {
    return false;
  }

  // undoing the change
  element.scrollTop = scrollTop;
  return true;
};

hakobpogh.dll
sumber
1

Hanya main-main di sini karena tidak ada solusi di atas yang berhasil untuk saya (sejauh ini). Saya telah menemukan beberapa keberhasilan dengan membandingkan scrollheight Div dengan offsetHeight-nya

var oh = $('#wrapDiv').get(0).offsetHeight;
var sh = $('#wrapDiv').get(0).scrollHeight;

Tampaknya memberi saya perbandingan yang akurat ... sejauh ini. Apakah ada yang tahu apakah ini sah?

Michael
sumber
2
Saya pikir Anda ingin scrollHeight dan clientHeight: stackoverflow.com/questions/4106538/…
rich remer
1

Untuk IE11 (Internet Explorer 11) saya harus mengubah logika menjadi:

// Subtract 3 (a small arbitrary number) to allow for IE reporting a difference of 1 when no scrollbar is present
var hasVerticalScrollbar = div.scrollHeight - 3 > div.clientHeight;

Ini karena IE melaporkan scrollHeight sebagai 1 lebih besar dari clientHeight ketika tidak ada scrollbar tetapi kira-kira 9 lebih besar saat scrollbar ada

danday74
sumber
0

Jika Anda perlu mengetahui apakah ada scrollbar untuk seluruh halaman web dan dengan dukungan browser lengkap, Anda dapat menggunakan ini:

const hasScrollbar = document.body.scrollHeight > window.innerHeight

Ini penting untuk digunakan window.innerHeightdaripada document.body.clientHeightkarena di beberapa browser seluler clientHeight tidak akan mendapatkan ukuran bilah alamat tetapi scrollHeight akan melakukannya, jadi Anda mendapatkan perhitungan yang salah.

Sebastian Hernandez
sumber
-5

tidak ada dari jawaban ini yang benar. Anda harus menggunakan ini:

var div = document.getElementById('container_div_id');

var hasHorizontalScrollbar = (div.offsetWidth > div.clientWidth);
var hasVerticalScrollbar = (div.offsetHeight > div.clientHeight);
hamid
sumber
Ini mendapat suara negatif karena mendapat salinan / tempel dari jawaban yang diterima dari 6 tahun yang lalu dan Anda tidak perlu tanda kurung untuk mengubah sesuatu menjadi boolean.
moto
-6

Tambahkan elemen lebar 100% di dalamnya. Kemudian setel overflow menjadi hidden. Jika gaya komputasi elemen (dari jQ) berubah, induk memiliki bilah gulir.

EDIT: Sepertinya Anda menginginkan metode lintas browser seperti getComputedStyle . Mencoba:

function getCSS(_elem, _style)
{
    var computedStyle;
    if (typeof _elem.currentStyle != 'undefined')
        computedStyle = _elem.currentStyle;
    else
        computedStyle = document.defaultView.getComputedStyle(_elem, null);
    return computedStyle[_style];
}
Soumya
sumber
1
Jika saya sudah menggunakan jQuery untuk ini, saya lebih suka melakukannya $(el).css("overflow/overflowX/overflowY")dan melihat apakah itu diatur ke otomatis atau gulir . Tapi saya ingin menghindari penggunaan jQuery.
Robert Koritnik
16
Gaya CSS TIDAK akan memberi tahu Anda apakah suatu elemen memiliki scrollbar atau tidak . Hanya apakah itu dapat memiliki scrollbar atau tidak . Mungkin menemukan metode lintas browser untuk menentukan lebar elemen dalam?
Soumya
@ Soumya92: Perbandingan ukuran antara ukuran scrollable dan ukuran sebenarnya adalah sepele dan saya telah menulisnya di atas ... Yang perlu saya periksa sekarang adalah untuk pengaturan overflow saat ini pada elemen tertentu.
Robert Koritnik
@ Soumya92: itulah yang saya butuhkan. Ini bisa sangat disederhanakan juga dengan menggunakan coalescecomputedStyle = el.currentStyle || document.defaultView.getComputedStyle(el, null);
Robert Koritnik
Satu hal lagi: Seberapa lintas browser ini? Browser mana yang didukung oleh ini?
Robert Koritnik