web-dev-qa-db-fra.com

Comment puis-je vérifier si une barre de défilement est visible?

Est-il possible de vérifier le overflow:auto d'un div?

Par exemple:

HTML

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

JQUERY

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

});

Parfois, le contenu est court (pas de barre de défilement) et parfois long (barre de défilement visible).

257
Peter

un petit plugin pour ça.

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

utilisez-le comme ça,

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

testé en travaillant sur Firefox, Chrome, IE6,7,8

mais ne fonctionne pas correctement sur le sélecteur de balises body

démo


Modifier

J'ai découvert que lorsque vous avez une barre de défilement horizontale qui fait apparaître la barre de défilement verticale, cette fonction ne fonctionne pas ....

J'ai trouvé une autre solution ... utilisez clientHeight

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

Peut-être une solution plus simple.

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

Je devrais changer une petite chose de ce que Reigel a dit:

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

innerHeight compte la hauteur du contrôle et ses rembourrages supérieur et inférieur

40
kpull1

Vous pouvez le faire en utilisant une combinaison des attributs Element.scrollHeight et Element.clientHeight .

Selon MDN:

L'attribut Element.scrollHeight en lecture seule est une mesure de la hauteur du contenu d'un élément, y compris du contenu non visible à l'écran en raison d'un débordement. La valeur scrollHeight est égale à la valeur minimale clientHeight requise par l'élément pour que tout le contenu puisse être contenu dans le point de vue sans passer par une barre de défilement verticale. le rembourrage d'élément mais pas sa marge.

Et:

La propriété Element.clientHeight en lecture seule renvoie la hauteur interne d'un élément en pixels, y compris le remplissage, mais pas la hauteur, la bordure ou la marge de la barre de défilement horizontale.

clientHeight peut être calculé comme hauteur CSS + remplissage CSS - hauteur de la barre de défilement horizontale (si présente).

Par conséquent, l'élément affichera une barre de défilement si la hauteur de défilement est supérieure à la hauteur du client. La réponse à votre question est donc:

_function scrollbarVisible(element) {
  return element.scrollHeight > element.clientHeight;
}
_
34
Ajedi32

Cela étend la réponse de @ Reigel. Il retournera une réponse pour les barres de défilement horizontales ou verticales.

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

Exemple:

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

Vous avez besoin de element.scrollHeight . Comparez-le avec $(element).height().

12
Boldewyn

J'ai créé un nouveau pseudo sélecteur personnalisé pour jQuery afin de tester si un élément possède l'une des propriétés CSS suivantes:

  1. débordement: [scroll | auto]
  2. débordement-x: [scroll | auto]
  3. débordement-y: [scroll | auto]

Je voulais trouver le parent scrollable le plus proche d'un autre élément, j'ai donc écrit un autre petit plugin jQuery pour trouver le parent le plus proche avec débordement.

Cette solution ne donne probablement pas les meilleurs résultats, mais elle semble fonctionner. Je l'ai utilisé en conjonction avec le plugin $ .scrollTo. Parfois, j'ai besoin de savoir si un élément se trouve dans un autre conteneur à défilement. Dans ce cas, je souhaite faire défiler l'élément parent défilable par rapport à la fenêtre.

J'aurais probablement dû emballer cela dans un seul plugin et ajouter le sélecteur psuedo comme faisant partie du plugin, ainsi que d'exposer une méthode 'la plus proche' pour trouver le conteneur à défilement le plus proche (parent).

Anywho .... le voici.

$. isScrollable plugin 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'
    );
};

$ (': scrollable') Pseudo-sélecteur jQuery:

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

$. scrollableparent () plugin jQuery:

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

La mise en œuvre est assez simple

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

UPDATE: J'ai découvert que Robert Koritnik avait déjà mis au point un pseudo sélecteur beaucoup plus puissant: permettant de faire défiler qui permet d'identifier les axes et la hauteur des conteneurs pouvant défiler, comme une partie de son plugin jQuery $ .scrollintoview (). plugin scrollintoview

Voici son pseudo sélecteur de fantaisie (accessoires):

    $.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();

    }

});
7
thegrandoverseer

La première solution ci-dessus ne fonctionne que dans IE La deuxième solution ci-dessus ne fonctionne que dans FF

Cette combinaison des deux fonctions fonctionne dans les deux navigateurs:

//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");
}​
  • Envelopper dans un document prêt
  • monitorWidth1: la div où le dépassement est défini sur auto
  • mtc: un conteneur div à l'intérieur de monitorWidth1
  • AdjustOverflowWidth: une classe CSS appliquée à la div #mtc lorsque la barre de défilement est active * Utilisez l'alerte pour tester plusieurs navigateurs, puis commentez le code de production final.

HTH

6
Aaron Hopkins

(scrollWidth/Height - clientWidth/Height) est un bon indicateur de la présence d'une barre de défilement, mais vous donnera une réponse "faux positif" à de nombreuses reprises. si vous avez besoin d'être précis, je vous suggère d'utiliser la fonction suivante. au lieu d'essayer de deviner si l'élément est scrollable - vous pouvez le faire défiler ...

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>
6
Yair Levy

Les réponses de tout le monde ici sont incomplètes, et cessons d'utiliser jquery dans SO réponses déjà s'il vous plaît. Consultez la documentation de jquery si vous voulez des informations sur jquery.

Voici une fonction purement javascript généralisée pour tester si un élément possède ou non des barres de défilement de manière complète:

// 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
B T

Les solutions fournies ci-dessus fonctionnent dans la plupart des cas, mais la vérification du scrollHeight et du débordement n'est parfois pas suffisante et échoue pour les éléments body et html: https://codepen.io/anon/pen/EvzXZw

Cette solution vérifie si l'élément est scrollable:

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

Remarque: Les éléments avec débordement = masqué sont également traités comme des éléments défilables ( plus d'informations ). Vous pouvez donc ajouter une condition à cet élément. aussi si nécessaire:

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

Explication: L'astuce, c'est que la tentative de défilement vers le bas et de revenir en arrière ne sera pas rendue par le navigateur. La fonction la plus haute peut également être écrite comme suit:

function isScrollableY (element) {
  // if scrollTop is not 0 / larger than 0, then the element is scrolled and therefore must be scrollable
  // -> true  
  if (element.scrollTop === 0) {
    // if the element is zero it may be scrollable  
    // -> try scrolling about 1 pixel
    element.scrollTop++;
    // if the element is zero then scrolling did not succeed and therefore it is not scrollable 
    // -> false  
    if (element.scrollTop === 0) return false;
    // else the element is scrollable; reset the scrollTop property
    // -> true
    element.scrollTop--;
  }
  return true;
}
2
Robbendebiene

Je vais m'étendre encore plus là-dessus pour ces pauvres âmes qui, comme moi, utilisent l'un des modernes js frameworks et non JQuery et ont été complètement abandonnées par les utilisateurs de ce fil:

ceci a été écrit en Angular 6 mais si vous écrivez React 16, Vue 2, Polymer, Ionic, React-Native, vous saurez quoi faire pour adaptez-le. Et c'est tout le composant, donc ça devrait être facile.

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,
) {}

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

dans le html, il y aurait une div avec la classe "elem-list" qui est stylisée dans le css ou le scss pour avoir un height et un overflow valeur qui n'est pas hidden. (donc auto ou sroll)

Je déclenche cette évaluation sur un événement de défilement car mon objectif final était d’avoir des "défilements à mise au point automatique" qui décident s’ils font défiler horizontalement l’ensemble des composants si ceux-ci ne disposent pas de défilement vertical. composants verticalement.

mais vous pouvez placer l'évaluation ailleurs pour qu'elle soit déclenchée par autre chose.

la chose importante à retenir ici est que vous n'êtes jamais forcé à utiliser JQuery, il existe toujours un moyen d'accéder aux mêmes fonctionnalités que celles utilisées sans l'utiliser.

2
tatsu

Voici une version améliorée de la réponse d'Evan qui semble rendre correctement compte de la logique de débordement.

            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
JBlitzen

La plupart des réponses présentées m'ont amené à proximité de l'endroit où je devais être, mais pas tout à fait là.

En gros, nous voulions évaluer si les barres de défilement - seraient - visibles dans une situation normale, ce qui signifie que la taille de l'élément body est plus grande que le port de vue. Ce n'était pas une solution présentée, c'est pourquoi je la soumets.

J'espère que ça aide quelqu'un!

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

Nous avons essentiellement la fonction hasScrollbar, mais elle est renvoyée si l'élément demandé est plus grand que le port d'affichage. Pour la taille du port de vue, nous venons d'utiliser $(window).height(). Une comparaison rapide de celle-ci avec la taille de l'élément donne les résultats corrects et le comportement souhaité.

0
Barry Chapman

Recherchez un parent de l'élément en cours doté d'un défilement vertical ou d'un corps.

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

Il peut être utilisé pour faire défiler automatiquement l'élément en cours via:

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

Fonctionne sur Chrome, Edge, Firefox et Opera, au moins dans les versions les plus récentes.

Utiliser JQuery ...

Configurez cette fonction pour corriger le pied de page:

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

Il retourne une fonction. Fait de cette façon juste pour définir le corps et le pied de page une fois.

Et ensuite, définissez ceci lorsque le document est prêt.

$(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);
});

Ajoutez ceci à votre css de pied de page:

footer {
    bottom: 0;
}
0
Mateus Pires

Voici mon amélioration: ajouté parseInt. pour une raison quelconque, cela ne fonctionnait pas sans elle.

// 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
Svetoslav Marinov