Search code examples
javascriptjqueryhorizontal-scrolling

Only show elements if container is scrollable


This is the code:

// if there is something to scroll horizontally then (but only for this container):

$(document).ready(function() {

  $(".scroll-area").scroll(function() {
    if ($(this).scrollLeft() > 0) {
      $(".left").css("display", "block");
    }

    if ($(this).scrollLeft() == 0) {
      $(".left").css("display", "none");
    }

    var fullWidth = $(this)[0].scrollWidth - $(this)[0].offsetWidth - 1;

    if ($(this).scrollLeft() >= fullWidth) {
      $(".right").css("display", "none");
    }

    if ($(this).scrollLeft() < fullWidth) {
      $(".right").css("display", "block");
    }

  });
});

// if there is nothing to scroll, don't show the gradients
* {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  font-size: 16px;
}

.container {
  width: 550px;
  height: 80px;
  background-color: grey;
  position: relative;
  margin-bottom: 20px;
}

.scroll-area {
  white-space: nowrap;
  overflow-x: auto;
  height: 100%;
}

.left,
.right {
  width: 50px;
  height: 100%;
  position: absolute;
  pointer-events: none;
  top: 0;
}

.left {
  background: linear-gradient(90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
  left: 0;
  display: none;
}

.right {
  background: linear-gradient(-90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
  right: 0;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

<div class="container">
  <div class="left"></div>
  <div class="right"></div>
  <div class="scroll-area">
    <div class="text">Scroll to right. Gradients are needed. This container works like expected. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</div>
  </div>
</div>

<div class="container">
  <div class="left"></div>
  <div class="right"></div>
  <div class="scroll-area">
    <div class="text">This container shouldn't show any gradient because nothing to scroll.</div>
  </div>
</div>

There should be an if function added. The logic should be: Show the gradient(s) only if there is something to scroll horizontally. If not, then hide the gradient(s). It should work with different containers independently on the same web page, and should update if the browser size changes.

Has someone an idea how to code that?


Solution

  • One way would be to loop thru all the .scroll-area elements and hide .left and .right elements if the scrollbar is visible. I added couple more containers to demonstrate:

    // if there is something to scroll horizontally then (but only for this container):
    
    $(document).ready(function() {
      $(".scroll-area").each(function(index) {
        if ($(this)[0].scrollWidth <= $(this)[0].clientWidth) {
          $(this).closest(".container").find(".left").css("display", "none");
          $(this).closest(".container").find(".right").css("display", "none");
        } else {
          $(this).scroll(function() {
            if ($(this)[0].scrollWidth > $(this)[0].clientWidth) {
              if ($(this).scrollLeft() > 0) {
                $(this).closest(".container").find(".left").css("display", "block");
              }
    
              if ($(this).scrollLeft() == 0) {
                $(this).closest(".container").find(".left").css("display", "none");
              }
    
              var fullWidth = $(this)[0].scrollWidth - $(this)[0].offsetWidth - 1;
    
              if ($(this).scrollLeft() >= fullWidth) {
                $(this).closest(".container").find(".right").css("display", "none");
              }
    
              if ($(this).scrollLeft() < fullWidth) {
                $(this).closest(".container").find(".right").css("display", "block");
              }
            }
          });
        }
      });
    });
    
    // if there is nothing to scroll, don't show the gradients
    * {
      margin: 0;
      padding: 0;
      font-family: sans-serif;
      font-size: 16px;
    }
    
    .container {
      width: 550px;
      height: 80px;
      background-color: grey;
      position: relative;
      margin-bottom: 20px;
    }
    
    .scroll-area {
      white-space: nowrap;
      overflow-x: auto;
      height: 100%;
    }
    
    .left,
    .right {
      width: 50px;
      height: 100%;
      position: absolute;
      pointer-events: none;
      top: 0;
    }
    
    .left {
      background: linear-gradient(90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
      left: 0;
      display: none;
    }
    
    .right {
      background: linear-gradient(-90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
      right: 0;
    }
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    
    <div class="container">
      <div id="x" class="left"></div>
      <div class="right"></div>
      <div id="a" class="scroll-area">
        <div class="text">Scroll to right. Gradients are needed. This container works like expected. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</div>
      </div>
    </div>
    
    <div class="container">
      <div id="y" class="left"></div>
      <div class="right"></div>
      <div id="b" class="scroll-area">
        <div class="text">This container shouldn't show any gradient because nothing to scroll.</div>
      </div>
    </div>
    
    <div class="container">
      <div id="y" class="left"></div>
      <div class="right"></div>
      <div id="b" class="scroll-area">
        <div class="text">This container shouldn't show any gradient because nothing to scroll.</div>
      </div>
    </div>
    
    <div class="container">
      <div id="x" class="left"></div>
      <div class="right"></div>
      <div id="a" class="scroll-area">
        <div class="text">Scroll to right. Gradients are needed. This container works like expected. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</div>
      </div>
    </div>