找到第一个可滚动的父级

时间:2016-03-11 12:06:55

标签: javascript html5 css3

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

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

我已经设置了演示here。使用按钮,您可以在两种不同情况之间切换

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

正文可滚动或.outer

有什么建议吗?

8 个答案:

答案 0 :(得分:39)

只检查滚动条是否可见,如果没有查看父项。

function getScrollParent(node) {
  if (node == null) {
    return null;
  }

  if (node.scrollHeight > node.clientHeight) {
    return node;
  } else {
    return getScrollParent(node.parentNode);
  }
}

答案 1 :(得分:33)

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

与我的端口的一个区别是,如果没有找到具有CSS overflow属性的正确值的父级,则返回<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;
}

答案 2 :(得分:8)

如果您使用的是jQuery UI,则可以使用scrollParent方法。请查看APIsource

来自API:

  

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

     

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

     

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

如果您不使用jQuery UI但使用的是jQuery,那么还有其他独立的库提供类似的功能,例如:

jquery-scrollparent

答案 3 :(得分:2)

大多数投票的答案都不适用scrollHeight > clientHeight即使没有滚动条也可以true,我找到了这个要点{{3} }

^写入代码的https://github.com/olahol/scrollparent.js/blob/master/scrollparent.js#L13总信用额度。

我将其重构为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 */
};

您可以像:

一样使用它
const $yourElement = document.querySelector('.your-class-or-selector');
getScrollParent($yourElement);

答案 4 :(得分:1)

我想你想要这个。

&#13;
&#13;
$('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;
  }
}
&#13;
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;
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 5 :(得分:0)

进一步建立在@Web_Designer's answer上,

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

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

然后尝试仅传递Dom Node element,如果元素是单个元素,则其驻留在数组键0上。例如。

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

答案 6 :(得分:0)

使用Google chrome开发工具,当您在页面上向下部分滚动时,检查页面,然后选择您认为可能是正在滚动的DOM节点。然后拉起控制台(从开发工具的“元素”选项卡中单击ESC),然后键入$0.scrollTop。这将打印出该元素的当前滚动位置。如果它不是0,那么您将知道那是正在滚动的元素。

答案 7 :(得分:0)

这是找到想要的东西的方式。

document.addEventListener('scroll', (e) => {
    console.log(e.target.scrollingElement.scrollTop);
})