Як я можу перевірити, чи видно смугу прокрутки?


277

Чи можна перевірити overflow:autoдіва?

Наприклад:

HTML

<div id="my_div" style="width: 100px; height:100px; overflow:auto;" class="my_class"> 
  * content
</div>

ПІДКЛЮЧЕННЯ

$('.my_class').live('hover', function (event)
{
    if (event.type == 'mouseenter')
    {
         if( ...  if scrollbar visible ? ... )
         {
            alert('true'):
         }
         else
         {
            alert('false'):
         }
    }

});

Іноді вміст короткий (смуга прокрутки), а іноді довгий (видно смугу прокрутки).

Відповіді:


376

невеликий плагін для нього.

(function($) {
    $.fn.hasScrollBar = function() {
        return this.get(0).scrollHeight > this.height();
    }
})(jQuery);

використовувати його так,

$('#my_div1').hasScrollBar(); // returns true if there's a `vertical` scrollbar, false otherwise..

перевірено, працюючи на Firefox, Chrome, IE6,7,8

але не працює належним чином на bodyселекторі тегів

демонстрація


Редагувати

Я дізнався, що у вас є горизонтальна смуга прокрутки, яка викликає появу вертикальної смуги прокрутки, ця функція не працює ....

Я знайшов інше рішення ... використання clientHeight

return this.get(0).scrollHeight > this.get(0).clientHeight;

22
Якщо у вас є підкладка, вам потрібно скористатися > this.innerHeight(); jsfiddle.net/p3FFL/210
— jcubic

2
У цьому є проблема, якщо горизонтальна смуга прокрутки також існує, то вона повернеться помилковою, навіть якщо вертикальна смуга прокрутки існує до тих пір, поки висота не зменшиться по горизонтальній висоті смуги прокрутки.
— Аллі

чому ви двічі визначили одну і ту ж функцію? @jcubic
— Nitin Sawant

8
Зауважте, що на Macs смуга прокрутки плаває над вмістом і зникає, коли не використовується. У Windows це завжди видно і займає горизонтальний простір. Тому, лише тому, що вміст може прокручуватися (який ця функція виявляє), це не означає, що смуга прокрутки обов'язково присутня.
— Андрій

2
(функція ($) {$ .fn.hasScrollBar = функція () {повернути це.get (0) .scrollWidth> this.width); }}) (jQuery); це працює для горизонтального перекриття. Підходить для перевірки чутливості мобільних пристроїв на веб-сайтах у iframes.
— Олександр Микола Попа

57

Можливо, більш просте рішення.

if ($(document).height() > $(window).height()) {
    // scrollbar
}

Ця відповідь спрацювала для мене після перевірки, чи готовий DOM за допомогою JQuery.ready()
— Simple Sandman

4
Це передбачає, що смуга прокрутки знаходиться у вікні, а не в роздільному елементі. Запропонуйте змінити посилання, щоб припустити: "Якщо вам потрібно лише протестувати смугу прокрутки в головному вікні, ви можете спробувати:"
— justdan23

43

Це можна зробити за допомогою комбінації атрибутів Element.scrollHeightта Element.clientHeightатрибутів.

За даними MDN:

Атрибут Element.scrollHeight лише для читання - це вимірювання висоти вмісту елемента, включаючи вміст, який не видно на екрані через переповнення. Значення scrollHeight дорівнює мінімальній клієнтській висоті, яку потребує елемент, щоб вмістити весь вміст у точці огляду без використання вертикальної смуги прокрутки. Вона включає в себе елемент прокладки, але не його запас.

І:

Element.clientHeight читання повертає тільки власності внутрішню висоту елемента в пікселях, в тому числі , але не оббивка горизонтальної смуги прокрутки, висота кордону або краю.

Висота клієнта може бути обчислена як висота CSS + обшивка CSS - висота горизонтальної смуги прокрутки (якщо є).

Тому елемент відобразить смугу прокрутки, якщо висота прокрутки перевищує висоту клієнта, тож відповідь на ваше запитання:

function scrollbarVisible(element) {
  return element.scrollHeight > element.clientHeight;
}

2
Наприклад: github.com/twbs/bootstrap/blob/master/js/modal.js#L242 та +1 для цитати та пояснення MDN!
— lowtechsun

в хромі, якщо вміст має межу, ніж він не включений у scrollHeight
— AT

1
Проголосовано за те, що не втрачає уваги та використання рамки / бібліотеки.
— Джон

Обережно - це спричиняє відтік, який є зливом продуктивності. gist.github.com/paulirish/5d52fb081b3570c81e3a
— Todd Sjolander

43

Я повинен трохи змінити те, що сказав Рейгель:

(function($) {
    $.fn.hasScrollBar = function() {
        return this[0] ? this[0].scrollHeight > this.innerHeight() : false;
    }
})(jQuery);

innerHeight підраховує висоту управління та його верхню та нижню прокладки


return (this.get (0))? this.get (0) .scrollHeight> this.innerHeight (): false;
— commonpike

3
Я думаю, що це слід визначити правильною відповіддю. Це працювало на FF35, IE11 та Chrome39.
— LucasBr

Він не перевіряє значення 'overflow', щоб переконатися, що рядки прокрутки з’являться, коли ця умова scrollHeight буде виконана.
— BT

1
@BT Але якщо в моєму файлі CSS переповнення встановлено на автоматичне, мені не потрібна додаткова перевірка? Він порівнює розміри і цього достатньо ...?
— Андрій

Відповідь, яка працює лише на вас, не є відповіддю. Як ви знаєте, що мають інші люди у своєму css? Ваша відповідь не згадує про це обмеження. Якщо хтось не може залишити вашу відповідь і змусити її працювати, це не є гарною відповіддю.
— BT

27

Це розгортається на відповідь @ Рейгеля. Він поверне відповідь на горизонтальну або вертикальну смуги прокрутки.

(function($) {
    $.fn.hasScrollBar = function() {
        var e = this.get(0);
        return {
            vertical: e.scrollHeight > e.clientHeight,
            horizontal: e.scrollWidth > e.clientWidth
        };
    }
})(jQuery);

Приклад:

element.hasScrollBar()             // Returns { vertical: true/false, horizontal: true/false }
element.hasScrollBar().vertical    // Returns true/false
element.hasScrollBar().horizontal  // Returns true/false


8

Я створив новий спеціальний: псевдоселектор для jQuery, щоб перевірити, чи є у елемента один із наступних властивостей css:

  1. переповнення: [прокручування | авто]
  2. overflow-x: [прокручування | авто]
  3. overflow-y: [прокручування | авто]

Я хотів знайти найближчий прокручуваний батько іншого елемента, тому я також написав ще один маленький плагін jQuery, щоб знайти найближчий з батьків із переповненням.

Це рішення, ймовірно, не найкраще, але, здається, працює. Я використовував його спільно з плагіном $ .scrollTo. Іноді мені потрібно знати, чи знаходиться елемент в іншому контейнері, який прокручується. У такому випадку я хочу прокрутити батьківський прокручуваний елемент проти вікна.

Я, мабуть, повинен був завернути це в один плагін і додати додаток селектора psuedo як частину плагіна, а також відкрити метод "найближчого", щоб знайти найближчий (батьківський) контейнер для прокрутки.

Anywho .... ось воно.

$ .isScrollable плагін jQuery:

$.fn.isScrollable = function(){
    var elem = $(this);
    return (
    elem.css('overflow') == 'scroll'
        || elem.css('overflow') == 'auto'
        || elem.css('overflow-x') == 'scroll'
        || elem.css('overflow-x') == 'auto'
        || elem.css('overflow-y') == 'scroll'
        || elem.css('overflow-y') == 'auto'
    );
};

$ (': прокручуваний') псевдоселектор jQuery:

$.expr[":"].scrollable = function(a) {
    var elem = $(a);
    return elem.isScrollable();
};

$ .scrollableparent () плагін jQuery:

$.fn.scrollableparent = function(){
    return $(this).closest(':scrollable') || $(window); //default to $('html') instead?
};

Реалізація досить проста

//does a specific element have overflow scroll?
var somedivIsScrollable = $(this).isScrollable();
//use :scrollable psuedo selector to find a collection of child scrollable elements
var scrollableChildren = $(this).find(':scrollable');
//use $.scrollableparent to find closest scrollable container
var scrollableparent = $(this).scrollableparent();

ОНОВЛЕННЯ: Я виявив, що Роберт Коритник вже придумав набагато більш потужний: прокручуваний псевдоселектор, який визначить прокручувані осі та висоту прокручуваних контейнерів, як частина його плагіна $ .scrollintoview () jQuery. плагін scrollintoview

Ось його фантазійний псевдоселектор (реквізит):

    $.extend($.expr[":"], {

    scrollable: function (element, index, meta, stack) {

        var direction = converter[typeof (meta[3]) === "string" && meta[3].toLowerCase()] || converter.both;

        var styles = (document.defaultView && document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(element, null) : element.currentStyle);

        var overflow = {

            x: scrollValue[styles.overflowX.toLowerCase()] || false,

            y: scrollValue[styles.overflowY.toLowerCase()] || false,

            isRoot: rootrx.test(element.nodeName)

        };



        // check if completely unscrollable (exclude HTML element because it's special)

        if (!overflow.x && !overflow.y && !overflow.isRoot)

        {

            return false;

        }



        var size = {

            height: {

                scroll: element.scrollHeight,

                client: element.clientHeight

            },

            width: {

                scroll: element.scrollWidth,

                client: element.clientWidth

            },

            // check overflow.x/y because iPad (and possibly other tablets) don't dislay scrollbars

            scrollableX: function () {

                return (overflow.x || overflow.isRoot) && this.width.scroll > this.width.client;

            },

            scrollableY: function () {

                return (overflow.y || overflow.isRoot) && this.height.scroll > this.height.client;

            }

        };

        return direction.y && size.scrollableY() || direction.x && size.scrollableX();

    }

});

6

Перше рішення вище працює лише в IE Друге вище рішення працює лише у FF

Ця комбінація обох функцій працює в обох браузерах:

//Firefox Only!!
if ($(document).height() > $(window).height()) {
    // has scrollbar
    $("#mtc").addClass("AdjustOverflowWidth");
    alert('scrollbar present - Firefox');
} else {
    $("#mtc").removeClass("AdjustOverflowWidth");
}

//Internet Explorer Only!!
(function($) {
    $.fn.hasScrollBar = function() {
        return this.get(0).scrollHeight > this.innerHeight();
    }
})(jQuery);
if ($('#monitorWidth1').hasScrollBar()) {
    // has scrollbar
    $("#mtc").addClass("AdjustOverflowWidth");
    alert('scrollbar present - Internet Exploder');
} else {
    $("#mtc").removeClass("AdjustOverflowWidth");
}​
  • Загорніть готовий документ
  • monitorWidth1: div, де переповнення встановлено в автоматичному режимі
  • mtc: роздільник контейнера всередині monitorWidth1
  • AdjustOverflowWidth: клас css, застосований до #mtc div, коли активна смуга прокрутки * Використовуйте попередження для тестування крос-браузера, а потім прокоментуйте остаточний код виробництва.

HTH


6

(scrollWidth / Height - clientWidth / Height) - хороший показник наявності смуги прокрутки, але вона багато разів дасть вам відповідь «помилково позитивно». якщо вам потрібно бути точним, я б запропонував використовувати наступну функцію. замість того, щоб намагатися вгадати, чи елемент прокручується - ви можете прокрутити його ...

function isScrollable( el ){
  var y1 = el.scrollTop;
  el.scrollTop  += 1;
  var y2 = el.scrollTop;
  el.scrollTop  -= 1;
  var y3 = el.scrollTop;
  el.scrollTop   = y1;
  var x1 = el.scrollLeft;
  el.scrollLeft += 1;
  var x2 = el.scrollLeft;
  el.scrollLeft -= 1;
  var x3 = el.scrollLeft;
  el.scrollLeft  = x1;
  return {
    horizontallyScrollable: x1 !== x2 || x2 !== x3,
    verticallyScrollable: y1 !== y2 || y2 !== y3
  }
}
function check( id ){
  alert( JSON.stringify( isScrollable( document.getElementById( id ))));
}
#outer1, #outer2, #outer3 {
  background-color: pink;
  overflow: auto;
  float: left;
}
#inner {
  width:  150px;
  height: 150px;
}
button {  margin: 2em 0 0 1em; }
<div id="outer1" style="width: 100px; height: 100px;">
  <div id="inner">
    <button onclick="check('outer1')">check if<br>scrollable</button>
  </div>
</div>
<div id="outer2" style="width: 200px; height: 100px;">
  <div id="inner">
    <button onclick="check('outer2')">check if<br>scrollable</button>
  </div>
</div>
<div id="outer3" style="width: 100px; height: 180px;">
  <div id="inner">
    <button onclick="check('outer3')">check if<br>scrollable</button>
  </div>
</div>


У яких випадках це дасть помилковий позитив?
— GaloisGirl

5

Ось відповіді всіх тут неповні, і дозволяємо перестати використовувати jquery в SO відповіді, будь ласка. Перевірте документацію jquery, якщо ви хочете отримати інформацію про jquery.

Ось узагальнена функція чистого JavaScript для тестування того, чи є елемент повністю прокладений:

// dimension - Either 'y' or 'x'
// computedStyles - (Optional) Pass in the domNodes computed styles if you already have it (since I hear its somewhat expensive)
function hasScrollBars(domNode, dimension, computedStyles) {
    dimension = dimension.toUpperCase()
    if(dimension === 'Y') {
        var length = 'Height'
    } else {
        var length = 'Width'
    }

    var scrollLength = 'scroll'+length
    var clientLength = 'client'+length
    var overflowDimension = 'overflow'+dimension

    var hasVScroll = domNode[scrollLength] > domNode[clientLength]


    // Check the overflow and overflowY properties for "auto" and "visible" values
    var cStyle = computedStyles || getComputedStyle(domNode)
    return hasVScroll && (cStyle[overflowDimension] == "visible"
                         || cStyle[overflowDimension] == "auto"
                         )
          || cStyle[overflowDimension] == "scroll"
}

4
Чому слід уникати використання jquery для питання, позначеного як jquery? Будь ласка, додайте посилання на згадувану вами частину документації jquery.
— kpull1

6
@ kpull1 Забагато людей позначає jQuery на кожне питання, що у них є JavaScript. Це запитання має відношення до jQuery. Там немає ні одна частини документації JQuery , який має відповідь, тому що JQuery не робити цього, і не повинна.
— BT

4

Я поширюся на це ще більше для тих бідних душ, які, як і я, використовують одну із сучасних фреймворків js, а не JQuery і були повністю покинуті людьми з цієї нитки:

це було написано у Angular 6, але якщо ви пишете React 16, Vue 2, Polymer, Ionic, React-Native, ви будете знати, що робити, щоб адаптувати його. І це весь компонент, тому це повинно бути легко.

import {ElementRef, AfterViewInit} from '@angular/core';

@Component({
  selector: 'app',
  templateUrl: './app.html',
  styleUrls: ['./app.scss']
})
export class App implements AfterViewInit {
scrollAmount;

constructor(
  private fb: FormBuilder,
  private element: ElementRef 
) {}

ngAfterViewInit(){
  this.scrollAmount = this.element.nativeElement.querySelector('.elem-list');
  this.scrollAmount.addEventListener('wheel', e => { //you can put () instead of e
  // but e is usefull if you require the deltaY amount.
    if(this.scrollAmount.scrollHeight > this.scrollAmount.offsetHeight){
       // there is a scroll bar, do something!
    }else{
       // there is NO scroll bar, do something!
    }
  });
}
}

у html був би div з класом "elem-list", який стилізований у css або scss, щоб мати а heightта overflowзначення, яке не є hidden. (так autoчиsroll )

Я запускаю цей евал на подію прокрутки, тому що моя кінцева мета полягала в тому, щоб мати «автоматичні свитки прокрутки», які вирішують, чи прокручують вони весь набір компонентів по горизонталі, якщо вказані компоненти не мають вертикальної прокрутки, а в іншому випадку лише прокручують нутрощі одного з компоненти вертикально.

але ви можете розмістити овал в іншому місці, щоб його викликало щось інше.

Тут важливо пам’ятати: ви ніколи не змушені використовувати JQuery, завжди є спосіб отримати доступ до тих же функцій, які він має, не використовуючи.


1
Цікаво, чому ви слухаєте події на колесах, щоб перевірити, чи є смуга прокрутки чи ні.
— mix3d

3
Крім того, оскільки ви використовуєте функції стрілок, thisзберігає батьківський обсяг; th = this;є непотрібним.
— mix3d

1
@ mix3d Я особисто використовую цей код для автоматичного перемикання між горизонтальною та вертикальною прокруткою, на основі якої є напрямок прокрутки в заданому загостреному елементі, який є динамічним
— tatsu

1
Re: це; це в основному синтаксичний цукор (плюс хороша стенограма) дляfunction(){}.bind(this)
— mix3d

1

Ось вдосконалена версія відповіді Евана, яка, здається, належним чином враховує логіку переповнення.

            function element_scrollbars(node) {
                var element = $(node);
                var overflow_x = element.css("overflow-x");
                var overflow_y = element.css("overflow-y");
                var overflow = element.css("overflow");
                if (overflow_x == "undefined") overflow_x == "";
                if (overflow_y == "undefined") overflow_y == "";
                if (overflow == "undefined") overflow == "";
                if (overflow_x == "") overflow_x = overflow;
                if (overflow_y == "") overflow_y = overflow;
                var scrollbar_vertical = (
                    (overflow_y == "scroll")
                    || (
                        (
                            (overflow_y == "hidden")
                            || (overflow_y == "visible")
                        )
                        && (
                            (node.scrollHeight > node.clientHeight)
                        )
                    )
                );
                var scrollbar_horizontal = (
                    (overflow_x == "scroll")
                    || (
                        (
                            (overflow_x == "hidden")
                            || (overflow_x == "visible")
                        )
                        && (
                            (node.scrollWidth > node.clientWidth)
                        )
                    )
                );
                return {
                    vertical: scrollbar_vertical,
                    horizontal: scrollbar_horizontal
                };
            }

1

Наведені вище рішення працюватимуть у більшості випадків, але перевірка висоти та переповнення прокрутки іноді недостатня і може не працювати з елементами body та html, як показано тут: https://codepen.io/anon/pen/EvzXZw

1. Рішення - Перевірте, чи елемент прокручується:

function isScrollableY (element) {
  return !!(element.scrollTop || (++element.scrollTop && element.scrollTop--));
}

Примітка: елементи з overflow: hiddenтакож розглядаються як прокручувані ( додаткова інформація ), тому ви можете також додати умову проти цього, якщо потрібно:

function isScrollableY (element) {
    let style = window.getComputedStyle(element);
    return !!(element.scrollTop || (++element.scrollTop && element.scrollTop--)) 
           && style["overflow"] !== "hidden" && style["overflow-y"] !== "hidden";
}

Наскільки я знаю, цей метод виходить з ладу лише в тому випадку, якщо елемент є scroll-behavior: smooth .

Пояснення: фокус полягає в тому, що браузер не намагається прокрутити спробу прокрутки вниз і повернути її назад. Найвищу функцію також можна записати так:

2. Рішення - зробіть усі необхідні перевірки:

function isScrollableY (element) {
  const style = window.getComputedStyle(element);
  
  if (element.scrollHeight > element.clientHeight &&
      style["overflow"] !== "hidden" && style["overflow-y"] !== "hidden" &&
      style["overflow"] !== "clip" && style["overflow-y"] !== "clip"
  ) {
    if (element === document.documentElement) return true;
    else if (style["overflow"] !== "visible" && style["overflow-y"] !== "visible") {
      // special check for body element (https://drafts.csswg.org/cssom-view/#potentially-scrollable)
      if (element === document.body) {
        const parentStyle = window.getComputedStyle(element.parentElement);
        if (parentStyle["overflow"] !== "visible" && parentStyle["overflow-y"] !== "visible" &&
            parentStyle["overflow"] !== "clip" && parentStyle["overflow-y"] !== "clip"
        ) {
          return true;
        }
      }
      else return true;
    }
  }
  
  return false;
}

0

Ось моє вдосконалення: додано parseInt. з якихось дивних причин не обійшлося без цього.

// usage: jQuery('#my_div1').hasVerticalScrollBar();
// Credit: http://stackoverflow.com/questions/4814398/how-can-i-check-if-a-scrollbar-is-visible
(function($) {
    $.fn.hasVerticalScrollBar = function() {
        return this.get(0) ? parseInt( this.get(0).scrollHeight ) > parseInt( this.innerHeight() ) : false;
    };
})(jQuery);

0

Працює на Chrome , Edge , Firefox та Opera , принаймні в нових версіях.

Використання JQuery ...

Налаштуйте цю функцію, щоб виправити колонтитул:

function fixFooterCaller()
{
    const body = $('body');
    const footer = $('body footer');

    return function ()
    {
        // If the scroll bar is visible
        if ($(document).height() > $(window).height())
        {
            // Reset
            footer.css('position', 'inherit');
            // Erase the padding added in the above code
            body.css('padding-bottom', '0');
        }
        // If the scrollbar is NOT visible
        else
        {
            // Make it fixed at the bottom
            footer.css('position', 'fixed');
            // And put a padding to the body as the size of the footer
            // This makes the footer do not cover the content and when
            // it does, this event fix it
            body.css('padding-bottom', footer.outerHeight());
        }
    }
}

Він повертає функцію. Зроблено таким чином, щоб один раз встановити тіло і колонтитул.

А потім встановіть це, коли документ буде готовий.

$(document).ready(function ()
{
    const fixFooter = fixFooterCaller();

    // Put in a timeout call instead of just call the fixFooter function
    // to prevent the page elements needed don't be ready at this time
    setTimeout(fixFooter, 0);
    // The function must be called every time the window is resized
    $(window).resize(fixFooter);
});

Додайте це до css footer:

footer {
    bottom: 0;
}

0

Більшість представлених відповідей мене наблизили до того, де я мав бути, але не зовсім там.

Ми в основному хотіли оцінити, чи будуть смуги прокрутки - видимими в звичайній ситуації, за цим визначенням, що означає, що розмір елемента тіла більше, ніж порт перегляду. Це не було представлене рішення, саме тому я його подаю.

Сподіваємось, це комусь допомагає!

(function($) {
    $.fn.hasScrollBar = function() {
        return this.get(0).scrollHeight > $(window).height();
    }
})(jQuery);

По суті, у нас є hasScrollbarфункція, але повертається, якщо запитуваний елемент більше, ніж порт перегляду. Для перегляду розміру порту ми щойно використовували $(window).height(). Швидке порівняння порівняно з розміром елемента дає правильні результати та бажану поведінку.


0

Знайдіть батьківський елемент поточного елемента, який має вертикальну прокрутку або тіло.

$.fn.scrollableParent = function() {
    var $parents = this.parents();

    var $scrollable = $parents.filter(function(idx) {
        return this.scrollHeight > this.offsetHeight && this.offsetWidth !== this.clientWidth;
    }).first();

    if ($scrollable.length === 0) {
        $scrollable = $('html, body');
    }
    return $scrollable;
};

Він може бути використаний для автоматичної прокрутки до поточного елемента за допомогою:

var $scrollable = $elem.scrollableParent();
$scrollable.scrollTop($elem.position().top);

0

Без рамкового підходу JavaScript, перевіряє вертикальність та горизонтальність

 /*
 * hasScrollBars
 * 
 * Checks to see if an element has scrollbars
 * 
 * @returns {object}
 */
Element.prototype.hasScrollBars = function() {
    return {"vertical": this.scrollHeight > this.style.height, "horizontal": this.scrollWidth > this.style.width};
}

Використовуйте його так

if(document.getElementsByTagName("body")[0].hasScrollBars().vertical){
            alert("vertical");
}

        if(document.getElementsByTagName("body")[0].hasScrollBars().horizontal){
            alert("horizontal");
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.