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


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.