Запретить прокрутку страницы при изменении данных во вложенной прокрутке в Chrome

#javascript #html #css #google-chrome

#javascript #HTML #css #google-chrome

Вопрос:

У меня есть элемент фиксированного размера на странице с «overflow: scroll», содержимое которого часто меняется. Я ожидаю, что изменения, произошедшие внутри этого элемента, могут повлиять на прокрутку этого элемента, но не на прокрутку страницы.

Но когда этот элемент находится в верхней части страницы, сама страница начинает прокручиваться. Как я могу это предотвратить?

Чтобы воспроизвести это поведение (у меня эта проблема в Chrome, но Firefox работает нормально):

  1. открыть https://jsfiddle.net/hd2Ltmu0/2 /
  2. начните прокручивать страницу до центра серого элемента
  3. подождите немного, и прокрутка страницы переместится вверх

Пример кода:

 <body>
    <div style="overflow-y: scroll;height: 300px">
        Content that changes often
    </div>
    Content that should not move even the upper block is changed
</body>
  

Ответ №1:

одно из хитрых решений — сохранить значение прокрутки перед добавлением содержимого и использовать его после:

 setInterval(function() {
 var s= $(window).scrollTop();
 $('.scrollable').children().first().remove();
 $('.scrollable').append('<div>' (Date.now()) '</div>');
 $(window).scrollTop(s);
}, 1000);

;  
 .demo {
  font-size: 24px;
}

.scrollable {
  height: 300px;
  overflow-y: scroll;
  background: #eee;
}  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="demo">
  String<br>
  String<br>
  String<br>
  String<br>
  <div class="scrollable">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
    <div>9</div>
    <div>10</div>
    <div>11</div>
    <div>12</div>
    <div>13</div>
    <div>14</div>
    <div>15</div>
</div>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
  String<br>
</div>  

Ответ №2:

Это происходит потому, что вы удаляете элемент из DOM, а затем добавляете новый, так что вы меняете высоту элемента на секунду, страница прокручивается.

вы должны заменить элемент вместо его удаления.

например — и это логически не то, что вы задумали:

 setInterval(function() {
 $('.scrollable').children().first().replaceWith('<div>' (Date.now()) '</div>');
}, 1000);
  

просто изменит элемент без изменения высоты или window.offset

Комментарии:

1. но почему изменение содержимого элемента заставляет страницу прокручиваться, поскольку этот элемент имеет фиксированную высоту? (обратите внимание, что это происходит только в Chrome)

2. Да, в этой демонстрации я могу сделать это, повторно используя существующие элементы DOM. Но в реальном приложении я не могу из-за анимации

Ответ №3:

В итоге я добавил пустой div шириной 1 пиксель. Кажется, что Chrome находит первый элемент сверху и перемещает прокрутку относительно этого элемента. Но мое решение довольно хакерское, и я не могу найти описание этого поведения ни в одной спецификации.

 <body>
    <div style="height: 300px; opacity: 0; width: 1px; float: left;">
    </div>
    <div style="overflow-y: scroll;height: 300px">
        Content that changes often
    </div>
    Content that should not move even the upper block is changed
</body>
  

https://jsfiddle.net/y3vtued6/