Найти первого прокручиваемого родителя

У меня есть такая ситуация, когда мне нужно прокрутить элемент в окне просмотра. Проблема в том, что я не знаю, какой элемент прокручивается. Например, в Portrait тело прокручивается, а в Landscape - другой элемент (и есть больше ситуаций, которые изменяют прокручиваемый элемент)

Теперь вопрос, заданный элементом, который нужно прокрутить в окне просмотра, как лучше всего найти свой первый прокручиваемый родитель?

Я установил демо здесь. С помощью кнопки вы можете переключаться между двумя различными ситуациями.

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

Тело прокручивается или .outer

Любые предложения?

Ответы

Ответ 1

Просто проверьте, видима ли полоса прокрутки, если вы не смотрите на родителя.

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

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

Ответ 2

Это чистый JS-порт метода jQuery UI scrollParent, который говорил cweston. Я пошел с этим, а не с принятым решением для ответа, которое не найдет родителя прокрутки, если еще нет переполнения содержимого.

Единственное отличие моего порта заключается в том, что если родительский элемент не найден с правильным значением для свойства CSS overflow, я возвращаю элемент <body>. Пользовательский интерфейс JQuery вместо этого возвратил объект 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;
}

Ответ 3

Если вы используете jQuery UI, вы можете использовать метод scrollParent. Посмотрите API или источник.

Из 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);

Ответ 5

Думаю, ты хочешь этого.

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

Ответ 6

Используя инструменты разработки Google Chrome, когда вы частично прокрутите страницу вниз, осмотрите страницу, выберите DOM-узел, который, по вашему мнению, может быть прокручиваемым. Затем откройте консоль (нажмите ESC на вкладке Элементы инструментов разработчика) и введите $0.scrollTop. Это распечатает текущую позицию прокрутки этого элемента. Если это не 0, то вы будете знать, что это элемент, который прокручивается.

Ответ 7

Опираясь на ответ @Web_Designer,

Если вы передаете jQuery object для этого элемента и получаете следующую ошибку,

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

Затем попробуйте передать только Dom Node element, который находится между ключами массива 0, если элемент является одним элементом. Например.

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