Вопрос или проблема
У меня есть элемент (контейнер) с горизонтальной прокруткой. Например:
<div class="rows">
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row">
<div id="container"></div>
</div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
</div>
Если переместить элемент в другую строку, горизонтальная прокрутка в контейнере сбросится. Почему это происходит? Как я могу сохранить позицию прокрутки? Возможно ли это исправить только с помощью CSS?
Вот демонстрация:
https://jsbin.com/gugotewane/2/edit?html,css,js,output
Можно воспользоваться трюком. Вы можете сохранить позицию прокрутки перед перемещением в другую строку.
document.getElementById("btn").addEventListener("click", function () {
const container = document.getElementById("container");
/* Сохраняя позицию прокрутки */
const scrollPosition = container.scrollLeft;
const currentRow = container.parentElement;
const nextRow = currentRow.nextElementSibling;
if (nextRow && nextRow.classList.contains("row")) {
nextRow.appendChild(container);
/* Устанавливаем позицию прокрутки после перемещения в другую строку */
container.scrollLeft = scrollPosition;
}
});
В вашем сниппете JSBin вы манипулируете DOM с помощью Javascript, удаляя одну строку и затем добавляя её в строку ниже. Это заставляет браузер повторно отрисовывать страницу и сбрасывать полосы прокрутки.
Чтобы решить эту проблему (снова на Javascript), вам нужно получить горизонтальную позицию прокрутки перед манипуляцией DOM с помощью:
let hscroll = container.scrollLeft;
А затем повторно применить горизонтальную прокрутку после добавления строки снова с помощью:
container.scrollLeft = hscroll;
где container
— это ваш элемент div
контейнера.
Причина сброса полос прокрутки (как горизонтальных, так и вертикальных) заключается в том, что браузеры повторно отрисовывают страницу после манипуляции DOM, и по умолчанию браузеры не запоминают позиции полос прокрутки.
Есть интересное свойство CSS, на которое вам может быть интересно обратить внимание, а именно: overflow-anchor
, которое, похоже, поддерживает позиции полос прокрутки после отрисовки.
Однако, после чтения CSS Scroll Anchoring, CSSWG, особенно Scroll Adjustment, оказывается, что якорная прокрутка применяется только к вертикальной прокрутке.
Так что я предполагаю, что это невозможно сделать только с помощью CSS.
document.getElementById("btn").addEventListener("click", function() {
const container = document.getElementById("container");
const currentRow = container.parentElement;
const nextRow = currentRow.nextElementSibling;
let hscroll = container.scrollLeft;
if (nextRow && nextRow.classList.contains("row")) {
nextRow.appendChild(container);
}
container.scrollLeft = hscroll;
});
.row {
padding: 20px;
min-height: 20px;
border-bottom: 1px solid black;
}
#container {
background-color: lightgray;
max-width: 100%;
overflow: auto;
padding: 20px;
}
.inner {
width: 3000px;
height: 20px;
background-color: blue;
padding: 20px 0 20px 400px;
}
<div class="rows">
<div class="row">
<div id="container">
<h2>
прокрутите меня, а затем нажмите кнопку >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
</h2>
<div class="inner">
<button id="btn">Переместить контейнер вниз</button>
</div>
<p>Он теряет позицию горизонтальной прокрутки.</p>
</div>
</div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
</div>
Ответ или решение
Для того чтобы сохранить положение горизонтальной прокрутки элемента при его перемещении, необходимо учитывать, что изменение DOM (Document Object Model) часто приводит к сбросу состояния прокрутки. Чтобы избежать этого, можно воспользоваться подходом, который заключается в сохранении текущей позиции прокрутки перед изменением и восстановлении её после.
Вот пример, как это можно реализовать с помощью JavaScript:
- Сохраните текущее положение прокрутки перед перемещением элемента.
- Выполните перемещение элемента в нужный контейнер.
- Восстановите сохраненное положение прокрутки после перемещения.
Пример кода
<div class="rows">
<div class="row">
<div id="container">
<h2>
Прокрутите меня, а затем нажмите кнопку >>>>>
</h2>
<div class="inner">
<button id="btn">Переместить контейнер вниз</button>
</div>
<p>Положение прокрутки будет потеряно без дополнительных действий.</p>
</div>
</div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
</div>
<style>
.row {
padding: 20px;
min-height: 20px;
border-bottom: 1px solid black;
}
#container {
background-color: lightgray;
max-width: 100%;
overflow: auto;
padding: 20px;
}
.inner {
width: 3000px;
height: 20px;
background-color: blue;
padding: 20px 0 20px 400px;
}
</style>
<script>
document.getElementById("btn").addEventListener("click", function () {
const container = document.getElementById("container");
const currentRow = container.parentElement;
const nextRow = currentRow.nextElementSibling;
// Сохраните текущее положение прокрутки
let hscroll = container.scrollLeft;
if (nextRow && nextRow.classList.contains("row")) {
nextRow.appendChild(container);
}
// Восстановите положение прокрутки после перемещения
container.scrollLeft = hscroll;
});
</script>
Объяснение:
-
HTML: Defines a layout with several rows and a container that will be moved.
-
CSS: Stylizes the rows and the container, ensuring that the container can scroll horizontally.
-
JavaScript:
- Устанавливает обработчик событий на кнопку.
- Сохраняет текущее положение прокрутки (свойство
scrollLeft
). - Перемещает контейнер вниз на следующую строку, если она существует.
- Восстанавливает положение прокрутки после перемещения.
Примечание о CSS
С помощью только CSS решение данной проблемы невозможно. Свойство overflow-anchor
действительно существует, но оно больше связано с вертикальной прокруткой, и его применение не повлияет на горизонтальную прокрутку. Поэтому JavaScript остается наиболее подходящим инструментом для данного случая.
Таким образом, сохранение и восстановление положения прокрутки при изменении структуры DOM возможно, и приведенный выше код иллюстрирует данный процесс.