2 maj 2019

Dodanie shadow podczas scroll - overflow

Podstawowe założenia:
1. Cień z prawej strony, jeżeli scroll jest na pozycji skrajnej lewej.

2. Cień z lewej strony, jeżeli scroll jest na pozycji skrajnej prawej.

3. Cień po lewej jak i prawej stronie równocześnie, gdy skroll się porusza 😉

Najpierw html

Budujemy div w którym dodajemy nasze elementy.

<div id="scrollbox">
  <ul id="myDIV">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    ...
  </ul>
</div>

Cień w za pomocą styli

Teraz nasz styl. Za jego pomocą wszystkie elementy li są w jednej linii.

#scrollbox {
  overflow-x: auto;
  width: 500px;
  max-height: 220px;
  margin: 50px auto;
}

#scrollbox ul {
  display: flex;
  flex-direction: row;
  white-space: nowrap;
  min-width: 100vw;
  height: 130px;
  margin: 0;
  padding: 0;
  list-style: none
}

#scrollbox ul li {
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  min-width: 130px;
  border: 1px solid red;
  margin: 0 2px
}

Aby dodać shadow należy odpowiednio dodać background-attachment do #scrollbox.

#scrollbox {
  overflow-x: auto;
  width: 500px;
  max-height: 220px;
  margin: 50px auto;
  background: linear-gradient(90deg, white 0%, rgba(255, 255, 255, 0)), linear-gradient(-90deg, white 0%, rgba(255, 255, 255, 0)) 100% 0, radial-gradient(farthest-side at 0% 50%, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), radial-gradient(farthest-side at 100% 50%, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)) 100% 0%;
  background-repeat: no-repeat;
  background-color: #fff;
  background-size: 100px 137px, 100px 137px, 14px 137px, 14px 137px;
  background-attachment: local, local, scroll, scroll
}

Niestety ale to rozwiązanie nie działa w IE czy w najnowszy Edge

Cień w za pomocą javascript

Tworzymy trzy class left-border, right-border oraz center-border
right-border dodajemy od razu do naszego głównego kontenera

<div id="scrollbox" class="right-border">

Zaś style to odpowiednio:

.left-border {
  box-shadow: inset 10px 0 5px -5px rgba(0, 0, 0, 0.25);
}

.right-border {
  box-shadow: inset -10px 0 5px -5px rgba(0, 0, 0, 0.25);
}

.center-border {
  box-shadow: inset 10px 0 5px -5px rgba(0, 0, 0, 0.25), inset -10px 0 5px -5px rgba(0, 0, 0, 0.25);
}

Teraz czas na javascript

function myFunction() {
  let el = document.getElementById("scrollbox");
  let div = document.getElementById("myDIV");

  console.log(el.scrollLeft, div.scrollWidth, el.offsetWidth);
  if (el.scrollLeft > 40) {
    addRemoveClass(el, "add", "center-border");
    addRemoveClass(el, "remove", "right-border");
  } else {
    addRemoveClass(el, "add", "right-border");
    addRemoveClass(el, "remove", "center-border");
  }
  if (el.scrollLeft < div.scrollWidth - el.offsetWidth) {
    addRemoveClass(el, "remove", "left-border");
  } else {
    addRemoveClass(el, "add", "left-border");
    addRemoveClass(el, "remove", "center-border");
  }
}

function addRemoveClass(el, type, className) {
  return el.classList[type](className);
}

window.addEventListener('load', () => {
  document.getElementById('scrollbox').addEventListener('scroll', addShadow);
})

W naszej funkcji najpierw dobieramy się do poszczególnych elementów. Głównego kontenera scrollbox później do kontenera z naszymi "klockami" li.
Za pomocą scrollLeft pobieram liczbę o którą został przesunięty kontener. Jeżeli jest większy niż 40 dodaję klasę center-border usuwam left-border
jeżeli mniejszy niż 40 robię odwrotnie, dodaję right usuwam center.

Niestety za pomocą własności scrollLeft jak sama nazwa wskazuje nie da się określi jak blisko jesteśmy prawej krawędzie obiektu aby dodać left-border.
Tutaj należy posłużyć się dwiema właściwościami scrollWith oraz offsetWith.
el.scrollLeft - da podaje nam szerokość o jaką przesunęliśmy nasz kontener z klockami względem głównego div - scrollbox, maksymalnie na prawo będzie 2218
div.scrollWidth - podaje nam dokładną szerokość kontenera myDiv z klockami
el.offsetWith - jest to szerokość scrollbox, szerokość ta została ustawiona na 500px i dodane zostało overflow-x: auto

el.scrollLeft sprawdzam czy jest mniejszy niż div.scrollWith - el.offsetWith jeżeli tak usuwam left-border jeżeli nie jest mniejszy to dodaję left-border i usuwam center-border

Ostatnia część to oczywiście nasłuchiwanie na zdarzenie "scroll" wywołujemy naszą funkcję "myFunction".

See the Pen
Adding shadow during scroll - overflow
by Greg (@Tomik23)
on CodePen.