web-dev-qa-db-ja.com

最初のスクロール可能な親を見つける

この状況では、要素をビューポートにスクロールする必要があります。問題は、スクロール可能な要素がわからないことです。たとえば、Portraitでは本文はスクロール可能で、Landscapeでは他の要素です(さらに、スクロール可能な要素を変更する状況がさらにあります)

さて、ビューポートにスクロールする必要がある要素がある場合、最初のスクロール可能な親を見つける最良の方法は何ですか?

デモをセットアップしました こちら 。ボタンを使用すると、2つの異なる状況を切り替えることができます

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

本文はスクロール可能または.outer

助言がありますか ?

36

親に見えない場合は、スクロールバーが表示されているかどうかを確認してください。

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

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

これは、jQuery UI scrollParentメソッドの純粋なJSポートであり、 cwestonの話 です。まだコンテンツがオーバーフローしていない場合、スクロールの親を見つけられない受け入れられた答えの解決策ではなく、私はこれを使いました。

私のポートとの1つの違いは、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;
}
36
Web_Designer

JQuery UIを使用している場合は、scrollParentメソッドを使用できます。 [〜#〜] api [〜#〜] または source をご覧ください。

APIから:

.scrollParent():スクロール可能な最も近い先祖要素を取得します

このメソッドは引数を受け入れません。このメソッドは、スクロールを許可する最も近い祖先を見つけます。つまり、.scrollParent()メソッドは、現在選択されている要素がスクロールする要素を見つけます。

注:このメソッドは、1つの要素を含むjQueryオブジェクトでのみ機能します。

JQuery UIを使用していないがjQueryを使用している場合、次のような同様の機能を提供する独立した代替ライブラリがあります。

jquery-scrollparent

8
cweston

ほとんどの投票での答えは、スクロールバーがなくてもscrollHeight > clientHeighttrueになる場合があります。

このGistソリューションを見つけました https://github.com/olahol/scrollparent.js/blob/master/scrollparent.js#L1

^ 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);
4
ncubica

Google chrome devツールを使用して、ページを部分的に下にスクロールしたら、ページを検査し、スクロールされていると思われるDOMノードを選択します。次にコンソールを引き上げます(開発ツールの[要素]タブからESCを押して)$0.scrollTop。これにより、その要素の現在のスクロール位置が出力されます。 0でない場合、それがスクロールされている要素であることがわかります。

1
Drew2

これが欲しいと思う。

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

@Stefano Nardoの回答から私はこれを書き直します。それは私のためにうまく機能します。

function getScrollParent(node){
   if(!node) return null;
   else if (node.scrollTop>0) return node;
   return getScrollParent(node.parentNode) || document.documentElement;
} 
0
dagalti

@ 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])
0