skip to Main Content

I have an element (container) with horizontal scroll. For example:

<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>

If you move the element to another row, it will reset the horizontal scroll in the container. Why is that? How can I maintain the scroll position? Is it possible to fix with only CSS?

Here’s a demo:
https://jsbin.com/gugotewane/2/edit?html,css,js,output

2

Answers


  1. A trick can do. you can preserve the scroll position before moving it to another row.

    document.getElementById("btn").addEventListener("click", function () {
      const container = document.getElementById("container");
      /* Stored the scroll position */
      const scrollPosition = container.scrollLeft;
      const currentRow = container.parentElement;
      const nextRow = currentRow.nextElementSibling;
    
      if (nextRow && nextRow.classList.contains("row")) {
        nextRow.appendChild(container);
        /* Set the scroll position after moving it to another row */
        container.scrollLeft = scrollPosition;
      }
    });
    
    Login or Signup to reply.
  2. In your JSBin snippet, you are manipulating the DOM with Javascript by removing one row and then appending it to the row below. This forces the browser to re-render the page and reset the scrollbars.

    To solve this problem (again in Javascript), you need to get the horizontal scroll position before manipulating the DOM with:

    let hscroll = container.scrollLeft;
    

    and then reapply the horizontal scroll after appending the row again with:

    container.scrollLeft = hscroll;
    

    where container is your container div element.

    The reason for the scrollbars (both horizontal and vertical scrollbars) resetting is that browsers re-render the page after the DOM is manipulated and by default the browsers do not remember the scrollbar positions.

    There is an interesting CSS property that you may be interested in looking at, namely: overflow-anchor which would appear to maintain the scrollbar positions after rendering.

    However, after reading CSS Scroll Anchoring, CSSWG, expecially Scroll Adjustment, it would appear that scroll anchoring only applies to vertical scrolling.

    So, I would guess that this is not possible only with 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>
            scroll me and then click button >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
          </h2>
          <div class="inner">
            <button id="btn">Move container down</button>
          </div>
          <p>It loses the horizontal scroll position.</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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search