Kiểm tra xem phần tử HTML có thanh cuộn hay không


113

Cách nhanh nhất để kiểm tra xem một phần tử có thanh cuộn là gì?

Một điều tất nhiên là kiểm tra xem phần tử có lớn hơn khung nhìn của nó hay không, điều này có thể dễ dàng thực hiện bằng cách kiểm tra hai giá trị sau:

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

nhưng điều đó không có nghĩa là nó cũng có thanh cuộn (vì vậy nó thực sự có thể được cuộn bởi con người).

Câu hỏi

Làm cách nào để kiểm tra thanh cuộn trong 1 trình duyệt chéo và chỉ 2 javascript (như không có jQuery )?

Chỉ Javascript, vì tôi cần chi phí càng nhỏ càng tốt, vì tôi muốn viết một bộ lọc bộ chọn jQuery rất nhanh

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

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

Tôi cho rằng tôi phải kiểm tra overflowcài đặt kiểu nhưng làm cách nào để thực hiện điều đó trong một trình duyệt chéo?

Chỉnh sửa bổ sung

Không chỉ overflowcài đặt phong cách. Kiểm tra xem một phần tử có thanh cuộn hay không không phải là chuyện nhỏ. Công thức đầu tiên tôi đã viết ở trên hoạt động tốt khi phần tử không có đường viền, nhưng khi nó có (đặc biệt khi đường viền có chiều rộng đáng kể), offsetkích thước có thể lớn hơn scrollkích thước nhưng phần tử vẫn có thể cuộn được. Chúng tôi thực sự phải trừ đường viền khỏi thứ offsetnguyên để có được khung nhìn có thể cuộn thực tế của phần tử và so sánh nó với thứ scrollnguyên.

Để tham khảo trong tương lai

:scrollableBộ lọc jQuery selector được bao gồm trong .scrollintoview()plugin jQuery của tôi . Mã hoàn chỉnh có thể được tìm thấy trong bài đăng trên blog của tôi nếu ai đó cần nó. Mặc dù nó không cung cấp giải pháp thực tế nhưng mã của Soumya đã giúp tôi giải quyết vấn đề một cách đáng kể. Nó chỉ tôi đi đúng hướng.

Câu trả lời:


118

Tôi đã tìm thấy cái này ở đâu đó vài tuần trước. Nó đã làm việc cho tôi.

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

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

/* you'll get true/false */

12
Rõ ràng bạn đã có một ví dụ đơn giản. Điều gì sẽ xảy ra nếu vùng chứa của bạn đã overflow:hiddenđặt trên đó? Sẽ có nội dung thừa nhưng nó vẫn không thể cuộn được. Vấn đề cho đến nay không đơn giản như nó có vẻ.
Robert Koritnik

7
Đây có thể không phải là giải pháp được chấp nhận, nhưng nó đã hiệu quả với tôi. Tôi không chắc tại sao bạn sẽ cuộn nó nếu nó bị ẩn.
vol7ron

Đây có thể không phải là giải pháp được chấp nhận, nhưng nó đã hiệu quả với tôi. Robert, đối với những trường hợp đó, bạn cũng không thể tìm nạp thuộc tính tràn css để kiểm tra những trường hợp đó (ví dụ div.scrollHeight>div.clientHeight && !(div.style.overflow && div.style.overflow == 'hidden'))?
vol7ron

7
Điều này không thành công trong nhiều trường hợp. Nếu phần tử của bạn bị tràn: hiển thị; chiều rộng: 200px; và có một con có chiều rộng 500px, phần tử của bạn không có thanh cuộn nhưng có Chiều rộng cuộn là 500px và Chiều rộng máy khách là 200px.
Joseph Lennox

1
Nếu phần tràn được hiển thị hoặc bị ẩn, thường không có thanh cuộn.
Hubert Grzeskowiak,

16

Thử:

Đối với thanh cuộn dọc

el.scrollHeight> el.clientHeight

Đối với thanh cuộn ngang

el.scrollWidth> el.clientWidth

Tôi biết điều này ít nhất cũng phù hợp với IE8 và Firefox 3.6+.


2
Tôi đã chỉ ra điều này có, điều này cho tôi biết một phần tử nhất định lớn hơn nó có vẻ, nhưng điều đó không có nghĩa là nó hiển thị thanh cuộn. Nó cũng có thể có overflow:hiddenvà nó sẽ không thể cuộn được nữa.
Robert Koritnik

1
Và việc kiểm tra với các giá trị clientHeight / clientWidth không cho kết quả tốt, vì các phần tử cũng có thể có đường viền, không được bao gồm trong thước đo này. Kiểm tra công thức của tôi. Nó hoạt động tốt hơn của bạn.
Robert Koritnik

Điều đó đúng khi sử dụng offsetHeight / offsetWidth để kiểm tra thanh cuộn thay vì clientHeight / clientWidth. Cảm ơn vì đã chỉ ra điều đó.
Gary

@RobertKoritnik - vì vậy chỉ cần kiểm tra xem phần tử cụ thể đó có overflow:hiddentrên đó không ... đây vẫn là câu trả lời chính xác theo quan điểm của tôi, vì nó là câu trả lời đơn giản nhất.
vsync

14

Điều này có vẻ (hoặc là) hơi khó hiểu, nhưng bạn có thể kiểm tra các thuộc tính scrollTopscrollLeft.

Nếu chúng lớn hơn 0, bạn biết rằng có thanh cuộn. Nếu chúng là 0, hãy đặt chúng thành 1 và kiểm tra lại chúng để xem bạn có nhận được kết quả là 1. Sau đó đặt chúng về 0.

Ví dụ: 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'));

Tôi tin rằng có một thuộc tính khác dành cho IE, vì vậy tôi sẽ cập nhật điều đó sau một phút.

EDIT: Xuất hiện như thể IE có thể hỗ trợ thuộc tính này. (Tôi không thể kiểm tra IE ngay bây giờ.)

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


Sẽ dễ dàng hơn nhiều để kiểm tra thanh cuộn nếu bạn so sánh offsetHeightclientHeight. Cái sau luôn nhỏ hơn kích thước thanh cuộn khi có thanh cuộn.
Robert Koritnik

@Robert: Không chắc về việc dễ dàng hơn, nhưng tôi thấy nó hoạt động như thế nào. Sau đó, tôi giả sử nếu một phần tử có overflow:scroll, bạn muốn phần tử đó được báo cáo là có thể cuộn cho dù thanh cuộn có được bật hay không. Tất nhiên giải pháp của tôi có thể có vấn đề nếu có một sự kiện onscroll đính kèm.
user113716

Không hẳn. Nếu bạn kiểm tra plugin jQuery của tôi, tôi phải tìm tổ tiên có thể cuộn thực sự nếu không tôi không thể cuộn một phần tử vào chế độ xem.
Robert Koritnik

8
@RobertKoritnik Không đúng; một số trình duyệt có thể có thanh cuộn không làm giảm chiều rộng. Trên OS X chẳng hạn. Hoặc chạm vào các thiết bị.
daniel.gindi

1
luôn luôn trả về false
Fatih Erol

14

Đây là một giải pháp khác:

Như một số người đã chỉ ra, chỉ đơn giản so sánh offsetHeight và scrollHeight là không đủ vì chúng khác nhau về các phần tử bị ẩn tràn, v.v., vẫn không có thanh cuộn. Vì vậy, ở đây tôi cũng đang kiểm tra xem tràn là cuộn hay tự động trên các kiểu được tính cho phần tử:

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

Nếu overflow*scrollsẽ luôn có một thanh cuộn, vì vậy tôi nghĩ rằng bạn muốn vertical: overflowY === 'scroll' || overflowY === 'auto' && node.scrollHeight > node.clientHeight, vv (tức là loại bỏ các dấu ngoặc để scroll*vs client*chỉ được kiểm tra khi overflow*auto). Nếu không, điều này có vẻ là giải pháp chính xác nhất.
Jake

@Jake Nếu scrollHeight <clientHeight khi cuộn tràn, các thanh cuộn sẽ ở đó nhưng chúng sẽ bị vô hiệu hóa (tức là phần tử không thể cuộn được). Vì vậy, tôi nghĩ rằng nó phụ thuộc vào ứng dụng. Sửa đổi của bạn là hợp lệ vì bạn chỉ muốn kiểm tra thanh cuộn, không quan trọng trạng thái. Đối với tôi, khi tôi nghĩ ra điều này, tôi đang tìm cách triển khai tự động cuộn cho một thành phần, vì vậy việc tắt thanh cuộn là vô ích trong trường hợp đó. Đó cũng dường như là trường hợp cho câu hỏi này (nó cần phải "được cuộn của con người")
lotif

6

Tôi có thể đến bữa tiệc hơi muộn, nhưng ...

Tôi tin rằng bạn có thể phát hiện thanh cuộn bằng e.offsetWidth so với e.clientWidth. Chiều rộng bù đắp bao gồm đường viền và thanh cuộn, phần đệm và chiều rộng. Chiều rộng máy khách bao gồm phần đệm và chiều rộng. Vui lòng xem:

https://developer.mozilla.org/en/DOM/element.offsetWidth (hình ảnh thứ hai) https://developer.mozilla.org/en/DOM/element.clientWidth (hình ảnh thứ hai)

Bạn cần kiểm tra:

  1. Phần tử có phần bổ sung được đặt thành tự động / cuộn (bao gồm cả trànX / Y) hay không bằng cách sử dụng kiểu tính toán / phân tầng / hiện tại.
  2. Nếu phần tử có phần tràn được đặt thành tự động / cuộn. Thiết lập offsetWidth và clientWidth.
  3. Nếu clientWidth nhỏ hơn offsetWidth - đường viền bên phải (được tìm lại thông qua kiểu computed / cascaded / current style), thì bạn biết mình có thanh cuộn.

Làm tương tự cho chiều dọc (offset / clientHeight).

IE7 báo cáo clientHeight bằng 0 cho một số phần tử (tôi chưa kiểm tra lý do tại sao), do đó bạn luôn cần kiểm tra tràn đầu tiên.

Hi vọng điêu nay co ich!


3

Có một số vấn đề trong trường hợp kiểm tra sự tồn tại của thanh cuộn, một trong số đó là trong mac bạn không có bất kỳ thanh cuộn nào có thể nhìn thấy được nên cả hai giải pháp trên đều không cho bạn câu trả lời chính xác.

Vì vậy, bởi vì hiển thị của trình duyệt không thường xuyên, bạn có thể kiểm tra cuộn có thay đổi cuộn và sau đó thiết lập lại:

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


1

Chỉ lộn xộn ở đây vì không có giải pháp nào ở trên phù hợp với tôi (cho đến nay). Tôi đã tìm thấy một số thành công khi so sánh chiều dài cuộn của Div với độ lệch của nó

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

Nó dường như cung cấp cho tôi một so sánh chính xác ... cho đến nay. Có ai đó biết nếu điều này là hợp pháp?


2
Tôi nghĩ rằng bạn muốn scrollHeight và clientHeight: stackoverflow.com/questions/4106538/...
remer giàu

1

Đối với IE11 (Internet Explorer 11), tôi đã phải thay đổi logic thành:

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

Điều này là do IE báo cáo scrollHeight lớn hơn 1 so với clientHeight khi không có thanh cuộn nhưng lớn hơn khoảng 9 khi có thanh cuộn


0

Nếu bạn cần biết nếu có thanh cuộn cho toàn bộ trang web và với sự hỗ trợ đầy đủ của trình duyệt, bạn có thể sử dụng cái này:

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

Điều quan trọng là sử dụng window.innerHeightthay document.body.clientHeightvì vì trong một số trình duyệt di động, clientHeight sẽ không nhận được kích thước của thanh địa chỉ nhưng scrollHeight sẽ nhận được, vì vậy bạn sẽ tính toán sai.


-5

không câu trả lời nào trong số này đúng. bạn phải sử dụng cái này:

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

var hasHorizontalScrollbar = (div.offsetWidth > div.clientWidth);
var hasVerticalScrollbar = (div.offsetHeight > div.clientHeight);

Điều này đã bị phản đối vì nó được sao chép / dán từ câu trả lời được chấp nhận từ 6 năm trước và bạn không cần dấu ngoặc đơn để biến một thứ gì đó thành boolean.
moto

-6

Thêm một phần tử rộng 100% bên trong nó. Sau đó, đặt tràn thành ẩn. Nếu kiểu tính toán của phần tử (từ jQ) thay đổi, phần tử gốc có một thanh cuộn.

CHỈNH SỬA: Có vẻ như bạn muốn một phương pháp trình duyệt chéo như getComputedStyle . Thử:

function getCSS(_elem, _style)
{
    var computedStyle;
    if (typeof _elem.currentStyle != 'undefined')
        computedStyle = _elem.currentStyle;
    else
        computedStyle = document.defaultView.getComputedStyle(_elem, null);
    return computedStyle[_style];
}

1
Nếu tôi đã sử dụng jQuery cho việc này, tôi chỉ muốn làm $(el).css("overflow/overflowX/overflowY")và xem liệu nó được đặt thành tự động hay cuộn . Nhưng tôi muốn tránh sử dụng jQuery.
Robert Koritnik

16
Các kiểu CSS sẽ KHÔNG cho bạn biết liệu một phần tử thanh cuộn hay không . Chỉ xem nó có thể có thanh cuộn hay không . Có thể tìm một phương pháp trình duyệt chéo để xác định chiều rộng của phần tử bên trong?
Soumya

@ Soumya92: So sánh kích thước giữa kích thước có thể cuộn và kích thước thực là không đáng kể và tôi đã viết nó ở trên ... Tất cả những gì tôi cần kiểm tra bây giờ là cài đặt tràn hiện tại trên một phần tử cụ thể.
Robert Koritnik

@ Soumya92: đó chính xác là những gì tôi cần. Nó có thể được đơn giản hóa rất nhiều cũng bằng cách sử dụng liên hiệpcomputedStyle = el.currentStyle || document.defaultView.getComputedStyle(el, null);
Robert Koritnik

Một điều nữa: Đây là trình duyệt chéo như thế nào? Những trình duyệt nào được hỗ trợ bởi điều này?
Robert Koritnik
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.