Javascript 找到第一个可滚动的父级

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35939886/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 18:24:05  来源:igfitidea点击:

Find first scrollable parent

javascripthtmlcss

提问by Jeanluca Scaljeri

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 body is scrollable and in Landscape its an other element (and there are more situation which change the scrollable element)

我有这种情况,我需要将元素滚动到视口中。问题是我不知道哪个元素是可滚动的。例如,在 Portrait 中,body 是可滚动的,而在 Landscape 中,它是另一个元素(并且有更多情况会改变可滚动元素)

Now the question, given an element which needs to be scrolled into the viewport, what is the best way to find its first scrollable parent ?

现在的问题是,给定一个需要滚动到视口中的元素,找到它的第一个可滚动父元素的最佳方法是什么?

I've setup a demo here. With the button you can toggle between two different situations

我在这里设置了一个演示。使用按钮,您可以在两种不同情况之间切换

<div class="outer">
    <div class="inner">
        <div class="content"> 
            ...
            <span>Scroll me into view</span>
        </div>
    </div>
</div>

The body is scrollable or .outer

正文是可滚动的或 .outer

Any suggestions ?

有什么建议 ?

回答by Stefano Nardo

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

回答by Web_Designer

This is a pure JS port of the jQuery UI scrollParentmethod 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.

这是cweston 所说的 jQuery UIscrollParent方法的纯 JS 端口。我选择了这个而不是接受的答案的解决方案,如果还没有内容溢出,它将找不到滚动父级。

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

与我的端口的一个不同之处在于,如果没有找到具有正确值的 CSSoverflow属性的父<body>元素,我将返回该元素。JQuery UI,而是返回document对象。这很奇怪,因为.scrollTop可以从 检索<body>但不能从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;
}

回答by cweston

If you are using jQuery UI you can use the scrollParentmethod. Have a look at the APIor the source.

如果您使用的是 jQuery UI,则可以使用该scrollParent方法。查看API源代码

From the API:

从API:

.scrollParent(): Get the closest ancestor element that is scrollable

This method does not accept any arguments. This method finds the nearest ancestor that allows scrolling. In other words, the .scrollParent()method finds the element that the currently selected element will scroll within.

Note: This method only works on jQuery objects containing one element.

.scrollParent(): 获取最近的可滚动的祖先元素

此方法不接受任何参数。此方法查找允许滚动的最近祖先。换句话说,该 .scrollParent()方法查找当前所选元素将在其中滚动的元素。

注意:此方法仅适用于包含一个元素的 jQuery 对象。

If you are not using jQuery UI but are using jQuery, then there are alternative independent libraries providing similar functionality, such as:

如果您不使用 jQuery UI 而是使用 jQuery,那么有替代的独立库提供类似的功能,例如:

jquery-scrollparent

jquery-scrollparent

回答by ncubica

the answer with most votes doesn't work in all cases scrollHeight > clientHeightcan be trueeven if there is no scrollbar.

即使没有滚动条,大多数投票的答案在所有情况下scrollHeight > clientHeight都不起作用true

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

我找到了这个要点解决方案https://github.com/olahol/scrollparent.js/blob/master/scrollparent.js#L13

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

^ 全部归功于编写代码的https://github.com/olahol

Refactored it to es6:

将其重构为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);

回答by Drew2

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.

使用谷歌浏览器开发工具,当您部分向下滚动页面时,检查页面,选择您认为可能正在滚动的 DOM 节点。然后调出控制台(在开发工具的 Elements 选项卡中按 ESC)并输入$0.scrollTop. 这将打印出该元素的当前滚动位置。如果它不是 0,那么您将知道这是正在滚动的元素。

回答by NiZa

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>

回答by Mohd Abdul Mujib

Building upon further on the @Web_Designer's answer,

进一步建立在@Web_Designer 的回答之上

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

如果您正在jQuery object为该元素传递并收到以下错误,

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

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

然后Dom Node element0如果元素是单个元素,请尝试只传递which btw 驻留在数组键中的元素。例如。

getScrollParent(jQuery("#" + formid)[0])