Find first scrollable parent

后端 未结 8 1255
南方客
南方客 2020-12-02 11:53

I have this situation in which I need to scroll an element into the viewport. The problem is that I don\'t know which element is scrollable. For example, in Portrait the bod

相关标签:
8条回答
  • 2020-12-02 12:36

    I think you want this.

    $('button').click(function() {
      $("body").addClass("body");
      $('.outer').toggleClass('scroller');
      check($(".content"));
    });
    
    function check(el) {
      var overflowY = el.css("overflow-y");  
      if (overflowY == "scroll") {
        alert(el.attr("class") + " has");
      } else {
        if(el.parent().length > 0)
       	  check(el.parent());
        else 
          return false;
      }
    }
    body {
      height: 450px;
      overflow-y: scroll;
    }
    
    div.inner {
      width: 200px;
      height: 400px;
      border: 1px solid #000;
    }
    
    div.outer {
      width: 200px;
      height: 200px;
    }
    
    div.outer.scroller {
      overflow-y: scroll;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <button>
      toggle
    </button>
    <div class="outer">
      <div class="inner">
        <div class="content">
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
          in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." adipiscing elit, sed do eiusmod tempor incididunt ut
          labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
          sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
        </div>
      </div>
    </div>

    0 讨论(0)
  • 2020-12-02 12:45

    Using google chrome dev tools, when you've scrolled partially down the page, inspect the page, select the DOM node that you think might be the one that is being scrolled. Then pull up the console (hit ESC from within the Elements tab of the dev tools) and type $0.scrollTop. This will print out the current scroll position of that element. If it is NOT 0 then you will know that that is the element that is being scrolled.

    0 讨论(0)
  • 2020-12-02 12:48

    Building upon further on the @Web_Designer's answer,

    If you are passing the jQuery object for that element and are getting the following error,

    Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'
    

    Then try passing just the Dom Node element which btw resides at array key 0 if the element is a single element. Eg.

    getScrollParent(jQuery("#" + formid)[0])
    
    0 讨论(0)
  • 2020-12-02 12:49

    Just check if the scrollbar is visible, if not look to the parent.

    function getScrollParent(node) {
      if (node == null) {
        return null;
      }
    
      if (node.scrollHeight > node.clientHeight) {
        return node;
      } else {
        return getScrollParent(node.parentNode);
      }
    }
    
    0 讨论(0)
  • 2020-12-02 12:53

    the answer with most votes doesn't work in all cases scrollHeight > clientHeight can be true even if there is no scrollbar.

    I found this gist solution https://github.com/olahol/scrollparent.js/blob/master/scrollparent.js#L13

    ^ total credit to https://github.com/olahol who wrote the code.

    Refactored it to es6:

    export const getScrollParent = (node) => {
      const regex = /(auto|scroll)/;
      const parents = (_node, ps) => {
        if (_node.parentNode === null) { return ps; }
        return parents(_node.parentNode, ps.concat([_node]));
      };
    
      const style = (_node, prop) => getComputedStyle(_node, null).getPropertyValue(prop);
      const overflow = _node => style(_node, 'overflow') + style(_node, 'overflow-y') + style(_node, 'overflow-x');
      const scroll = _node => regex.test(overflow(_node));
    
      /* eslint-disable consistent-return */
      const scrollParent = (_node) => {
        if (!(_node instanceof HTMLElement || _node instanceof SVGElement)) {
          return;
        }
    
        const ps = parents(_node.parentNode, []);
    
        for (let i = 0; i < ps.length; i += 1) {
          if (scroll(ps[i])) {
            return ps[i];
          }
        }
    
        return document.scrollingElement || document.documentElement;
      };
    
      return scrollParent(node);
      /* eslint-enable consistent-return */
    };
    

    you can use it like:

    const $yourElement = document.querySelector('.your-class-or-selector');
    getScrollParent($yourElement);
    
    0 讨论(0)
  • 2020-12-02 12:54

    This is a pure JS port of the jQuery UI scrollParent method that cweston spoke of. I went with this rather than the accepted answer's solution which will not find the scroll parent if there's no content overflow yet.

    The one difference with my port is that, if no parent is found with the right value for the CSS overflow property, I return the <body> element. JQuery UI, instead returned the document object. This is odd as values like .scrollTop can be retrieved from the <body> but not the document.

    function getScrollParent(element, includeHidden) {
        var style = getComputedStyle(element);
        var excludeStaticParent = style.position === "absolute";
        var overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/;
    
        if (style.position === "fixed") return document.body;
        for (var parent = element; (parent = parent.parentElement);) {
            style = getComputedStyle(parent);
            if (excludeStaticParent && style.position === "static") {
                continue;
            }
            if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) return parent;
        }
    
        return document.body;
    }
    
    0 讨论(0)
提交回复
热议问题