Slajder produktów v4 — wariant D

Klasy na module Galeria: sp3-slajder sp3-strona
To wariant C przestawiony na przesuw strona po stronie. Kod modułu jest ten sam — różnicę robi jedna klasa.

Co zmienia klasa sp3-strona

  • --sp3-przesuw: 100% — przeskok o całą szerokość okna galerii zamiast o jeden kafel
  • --sp3-przejscie: 2200 — wolniejszy przejazd, bo droga jest kilka razy dłuższa
  • --sp3-przerwa: 4500 — dłuższy postój, żeby slajder nie był w ruchu niemal bez przerwy

Jak liczona jest strona

Slajder nie odmierza pikseli na sztywno. Przeskakuje o tyle kafli, ile trzeba, żeby pokryć całe okno, i zatrzymuje się na krawędzi kafla — więc przy lewym brzegu nigdy nie sterczy ucięte zdjęcie. Skok bywa dlatego trochę dłuższy niż samo okno.

Liczba kafli w kroku dobiera się sama. Tam, gdzie w szeregu stoi zdjęcie poziome, jedna strona to mniej kafli, bo są prawie trzy razy szersze niż drzwi.

Do porównania

  • Wariant C — ta sama geometria, przesuw o jeden kafel
  • Warianty A i B — kafle kadrowane, równa szerokość, napis z boku
  • Wersja 1 — galeria ukryta, struktura budowana od zera

Kod do skopiowania

Ten sam kod obsługuje wariant C i D — o zachowaniu decydują klasy na module Galeria.

<style>
/* =====================================================
   SLAJDER PRODUKTOW v3 (wariant C) - sama Galeria Divi
   Klasa na module Galeria:  sp3-slajder
   Powiekszenie: wbudowane w Divi (jak w wariancie A).

   Roznica wobec v2: kafle maja WSPOLNA WYSOKOSC, ale
   szerokosc kazdy swoja - zdjecie widac w calosci, nic nie
   jest kadrowane. Bez napisu z boku i bez przyciemnienia.
   ===================================================== */

.sp3-slajder{
  --sp3-wysokosc: 260px;     /* wspolna wysokosc wszystkich kafli */
  --sp3-odstep: 30px;        /* przerwa miedzy kaflami */
  --sp3-przerwa: 3000;       /* co ile ms nastepny krok */
  --sp3-przejscie: 1500;     /* jak dlugo trwa krok */
  --sp3-powiekszenie: 1.05;  /* o ile rosnie kafel po najechaniu */
  --sp3-zolty: #F0C609;

  /* WIELKOSC PRZESUWU. Dwa sposoby zapisu:
       1     - o jeden kafel (2, 3 ... o tyle kafli)
       50%   - o polowe szerokosci okna galerii
       100%  - o cale okno, czyli "strona po stronie"
     Przy zapisie procentowym slajder przesuwa sie o tyle KAFLI, ile
     trzeba, zeby pokryc zadana czesc okna - dzieki temu zawsze konczy
     na krawedzi kafla i nic nie zostaje przeciete. */
  --sp3-przesuw: 1;

  overflow: hidden;
  padding-bottom: 26px;      /* miejsce na kafel rosnacy w dol */
}

/* GOTOWA NASTAWA: przesuw strona po stronie.
   Klasy na module Galeria: sp3-slajder sp3-strona
   Dluzszy skok wymaga wolniejszego przejazdu i dluzszego postoju,
   inaczej slajder niemal caly czas jest w ruchu. */
.sp3-slajder.sp3-strona{
  --sp3-przesuw: 100%;
  --sp3-przejscie: 2200;
  --sp3-przerwa: 4500;
}

/* siatka galerii staje sie torem slajdera */
.sp3-slajder .et_pb_gallery_items{
  display: flex !important;
  flex-wrap: nowrap !important;
  align-items: flex-start;
  gap: var(--sp3-odstep);
  will-change: transform;
}

/* kafel bierze szerokosc ze swojego zdjecia */
.sp3-slajder .et_pb_gallery_item{
  flex: 0 0 auto !important;
  width: auto !important;
  margin: 0 !important;
  padding: 0 !important;
  float: none !important;
  clear: none !important;
  position: relative;
  overflow: hidden;
  transform-origin: top center;
  transition: transform .5s cubic-bezier(.2,0,.2,1), box-shadow .5s ease;
}
.sp3-slajder .et_pb_gallery_item:hover{
  transform: scale(var(--sp3-powiekszenie));
  z-index: 5;
  box-shadow: 0 0 20px 0 rgba(0,0,0,.35);
}

/* wspolna wysokosc, szerokosc z proporcji pliku - zdjecie w calosci */
.sp3-slajder .et_pb_gallery_image{
  display: block;
  position: relative;
  overflow: hidden;
  height: var(--sp3-wysokosc);
  margin: 0 !important;
}
.sp3-slajder .et_pb_gallery_image a{ display:block; height:100%; position:relative; }
.sp3-slajder .et_pb_gallery_image img{
  display: block;
  height: var(--sp3-wysokosc);
  width: auto;
  max-width: none;
}

/* wlasna nakladka zamiast lupki Divi */
.sp3-slajder .et_overlay{ display:none !important; }

/* zolty kwadrat + dwie kreski jadace od krawedzi = plus */
.sp3-slajder .et_pb_gallery_image a::before{
  content:""; position:absolute; inset:0; z-index:3; opacity:0;
  background-image:
    linear-gradient(#fff,#fff),
    linear-gradient(#fff,#fff),
    linear-gradient(var(--sp3-zolty),var(--sp3-zolty));
  background-repeat:no-repeat;
  background-size:3px 26px, 26px 3px, 56px 56px;
  background-position:50% 0%, 0% 50%, 50% 50%;
  transition:opacity .25s ease, background-position .5s cubic-bezier(.2,0,.2,1);
  pointer-events:none;
}
.sp3-slajder .et_pb_gallery_item:hover .et_pb_gallery_image a::before{
  opacity:1;
  background-position:50% 50%, 50% 50%, 50% 50%;
}

/* elementy galerii zbedne w slajderze */
.sp3-slajder .et_pb_gallery_title,
.sp3-slajder .et_pb_gallery_caption,
.sp3-slajder .et_pb_gallery_pagination{ display:none !important; }

/* strzalki dokladane przez JS */
.sp3-slajder .sp3-arrows{ display:flex; gap:48px; justify-content:center; margin-top:10px; }
.sp3-slajder .sp3-arrows button{
  background:none; border:0; cursor:pointer; color:var(--sp3-zolty);
  font:600 14px/1 Poppins,system-ui,Arial,sans-serif; letter-spacing:2px;
  display:inline-flex; align-items:center; gap:10px; padding:8px;
}
.sp3-slajder .sp3-arrows button:hover{ color:#323232; }
.sp3-slajder .sp3-prev::before{ content:"\2190"; font-size:19px; }
.sp3-slajder .sp3-next::after{ content:"\2192"; font-size:19px; }

@media (max-width:990px){ .sp3-slajder{ --sp3-wysokosc:210px; } }
@media (max-width:590px){ .sp3-slajder{ --sp3-wysokosc:170px; --sp3-odstep:15px; } }
</style>

<script>
(function(){
  function start(){
    document.querySelectorAll('.sp3-slajder').forEach(function(root){
      if(root.dataset.sp3) return; root.dataset.sp3 = '1';

      var tor = root.querySelector('.et_pb_gallery_items');
      if(!tor || !tor.children.length) return;

      var styl = getComputedStyle(root);
      var PRZERWA   = parseFloat(styl.getPropertyValue('--sp3-przerwa'))   || 3000;
      var PRZEJSCIE = parseFloat(styl.getPropertyValue('--sp3-przejscie')) || 1500;
      var PRZESUW   = (styl.getPropertyValue('--sp3-przesuw') || '1').trim() || '1';

      var oryg = tor.children.length;
      tor.innerHTML = tor.innerHTML + tor.innerHTML;   /* klon -> plynne zapetlenie */

      var strzalki = document.createElement('div');
      strzalki.className = 'sp3-arrows';
      strzalki.innerHTML = '<button class="sp3-prev" type="button">PREV</button>'
                         + '<button class="sp3-next" type="button">NEXT</button>';
      root.appendChild(strzalki);

      var offset = 0, idx = 0, tween = null, ostatni = null;
      var doNastepnego = PRZERWA, najechane = false;
      var bezRuchu = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

      /* Kafle maja rozne szerokosci, wiec krok NIE jest stala liczba pikseli.
         Celem jest zawsze lewa krawedz kafla o danym numerze. */
      function pozycja(i){
        return tor.children[i].offsetLeft - tor.children[0].offsetLeft;
      }
      function jednostka(){ return pozycja(oryg); }   /* dlugosc jednego kompletu */
      function ease(p){ return 1 - Math.pow(1 - p, 3); }

      function normalizuj(){
        while(idx >= oryg){ idx -= oryg; offset -= jednostka(); }
        while(idx < 0){ idx += oryg; offset += jednostka(); }
      }

      /* Ile kafli przeskoczyc w jednym kroku.
         Zapis liczbowy - tyle kafli. Zapis procentowy - tyle kafli,
         ile trzeba, zeby przejechac zadana czesc okna galerii. */
      function ileKafli(){
        if(PRZESUW.charAt(PRZESUW.length - 1) === '%'){
          var cel = root.clientWidth * (parseFloat(PRZESUW) || 100) / 100;
          var start = pozycja(idx);
          var n = 1;
          while(n < oryg && pozycja(idx + n) - start < cel) n++;
          return n;
        }
        return Math.min(oryg, Math.max(1, parseInt(PRZESUW, 10) || 1));
      }

      function przesun(kierunek, czas){
        if(tween){ offset = tween.to; idx = tween.idx; tween = null; normalizuj(); }
        var ile = ileKafli();
        while(idx + kierunek * ile < 0){   /* cofamy sie z poczatku - przeskakujemy o komplet */
          offset += jednostka();
          idx += oryg;
        }
        var nowy = idx + kierunek * ile;
        tween = { from: offset, to: pozycja(nowy), start: performance.now(), dur: czas, idx: nowy };
      }

      strzalki.querySelector('.sp3-prev').addEventListener('click', function(){ przesun(-1, 450); doNastepnego = PRZERWA; });
      strzalki.querySelector('.sp3-next').addEventListener('click', function(){ przesun( 1, 450); doNastepnego = PRZERWA; });

      root.addEventListener('mouseenter', function(){ najechane = true; });
      root.addEventListener('mouseleave', function(){ najechane = false; });

      function klatka(t){
        if(ostatni === null) ostatni = t;
        var dt = t - ostatni; ostatni = t;

        if(tween){
          var p = (t - tween.start) / tween.dur;
          if(p >= 1){
            offset = tween.to; idx = tween.idx; tween = null;
            normalizuj();
            doNastepnego = PRZERWA;
          } else {
            offset = tween.from + (tween.to - tween.from) * ease(p);
          }
        } else if(!najechane && !bezRuchu){
          doNastepnego -= dt;
          if(doNastepnego <= 0) przesun(1, PRZEJSCIE);
        }

        tor.style.transform = 'translateX(' + (-offset) + 'px)';
        requestAnimationFrame(klatka);
      }
      requestAnimationFrame(klatka);
    });
  }
  if(document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start);
  else start();
})();
</script>