csstailwind-css

show more/show less button causes page to jump when clicked


On my website, I have a reviews section similar to the one on the official Tailwind CSS website.

In my reviews section, I have a button you can press to show more or show less reviews.

The show more feature works fine, but when I press the button again to show less reviews, the page moves a lot.

I'm not sure how to stop the page from moving when the "show less" part happens.

To reproduce bug

  1. visit https://lagoswashing.netlify.app/
  2. scroll down to reviews section, titled "Google & Facebook reviews"
  3. click "show more..."
  4. scroll down until you see the button again
  5. click button again with text "okay i get the point" (this will show less reviews)
  6. the page will move

https://tailwindcss.com has a working solution on their website (it's the second section) but I haven’t been able to figure out how they prevent the page from jumping when the reviews are collapsed.

Here is a minimal code example

    const toggleButton = document.getElementById("toggle-button")

    const grid = document.getElementById("grid")

    let isCollapsed = false

    toggleButton.addEventListener("click", () => {
      isCollapsed = !isCollapsed

      if (isCollapsed) {
        grid.classList.add("collapsed")
      } else {
        grid.classList.remove("collapsed")
      }
    })
    body {
      padding: 72px;
    }

    .filler-content {
      background: seashell;
      width: 100%;
      height: 1600px;
    }

    #grid {
      background: black;
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 16px;
    }

    .grid-item {
      background: lightblue;
      padding: 80px;
    }

    #toggle-button {
      background: orange;
      padding: 16px;
      position: fixed;
      bottom: 4px;
    }

    .collapsed {
      max-height: 20rem;
      overflow: hidden;
    }
    <div class="filler-content">this is filler content... scroll down</div>
    
    <section>
      <p>scroll down more until you see next message</p>
      <div id="grid">
        <div class="grid-item">review1</div>
        <div class="grid-item">review2</div>
        <div class="grid-item">review3</div>
        <div class="grid-item">review4</div>
        <div class="grid-item">review5</div>
        <div class="grid-item">review6</div>
        <div class="grid-item">review7</div>
        <div class="grid-item">review8</div>
        <div class="grid-item">review9</div>
        <div class="grid-item">review10</div>
        <div class="grid-item">review11</div>
        <div class="grid-item">review12</div>
        <div class="grid-item">review13</div>
        <div class="grid-item">review14</div>
        <div class="grid-item">review15</div>
        <div class="grid-item">review16</div>
        <div class="grid-item">review17</div>
      </div>
    
      <div id="toggle-button">Show less/Show more reviews</div>
    </section>
    
    <div class="filler-content">this is filler content.. click the orange button when it is below this sentence</div>


Solution

  • The tailwind website does not work how you think it does. In that:

    they do not "stop the page from moving"

    instead

    they do "move you back to the start of the section".

    The user has already scrolled("moved") the page. When you collapse your grid, the scroll position will remain where the user last put it. This is not only expected, but crucial to creating webpage dynamics function across renders.

    In order to achieve the effect you mention, you need to scroll the page back to the start of your grid section. You can achieve this by changing your event listener as follows:

    toggleButton.addEventListener("click", () => {
      isCollapsed = !isCollapsed;
    
      if (isCollapsed) {
        grid.classList.add("collapsed");
        grid.scrollIntoView();
      } else {
        grid.classList.remove("collapsed");
      }
    })