找到第一个可滚动的父级

问题描述 投票:31回答:7

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

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

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

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

身体是可滚动的或.outer

有什么建议 ?

javascript html5 css3
7个回答
41
投票

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

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

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

36
投票

这是scrollParent的jQuery UI cweston spoke of方法的纯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;
}

8
投票

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

来自API:

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

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

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

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

jquery-scrollparent


4
投票

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

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

^对编写代码的https://github.com/olahol的总功劳。

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

1
投票

我想你想要这个。

$('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>

1
投票

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


0
投票

@Web_Designer's answer的基础上进一步发展,

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

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

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

getScrollParent(jQuery("#" + formid)[0])
© www.soinside.com 2019 - 2024. All rights reserved.