Slider - Vanilla JS

horizontal Slider

horizontal Fader

vertical Slider

Slider auf JavaScript Basis habe ich schon einige geschrieben, nun aber versuche ich es mit einem anderen Ansatz, für das Sliden möchte ich das über CSS gestaltete Scrollen nutzen, dadurch ist die Umsetzung der Touch- und Wheel-Events nicht erforderlich, da es im Standard schon funktioniert.

Als Methoden zur Animierung sollen dann zusätzlich zum Wischen und Mousewheel/Mouspad (2-Finger), noch Pfeile (vorwärts/rückwärts), Bubbes (Punkte zur Steuerung und Anzeige aktiver Slide) oder Thumbnails (Bilder zur Steuerung und Anzeige aktiver Slide) und eine Autoplay Funktion (optional mit Play & Pause Button).

Das Sliden soll in horizontaler aber auch vertikaler Richtung funktionieren und Hintergrund-Bilder unterstützen.

Für ältere Browser wie den Internet Explorer habe ich noch den smooth scroll über requestAnimationFrame realisiert.

  • class="slides" : assign this object
  • class="horizontal" : horizontal Slider
  • class="vertical" : vertical Slider
  • class="arrows-outside" : position of arrows outside the slider
  • class="fade" : use fading not slide to change item
  • class="ratio44" : use aspect ratio of 44%, for silder with no content only background images
  • data-options="bubbles" : display small active links (for example circles) for navigation
  • data-options="thumbs" : display small active thumbnails for navigation
  • data-options="arrows" : display arrows to navigate
  • data-options="autoplay" : use interval to change slide
  • data-options="play_pause" : display play/pause button to interrupt sliding
  • data-options="loop" : loop endless default disabled (on autoplay also loop is enabled)
  • data-interval="3000" : time for autoplay to move to next slide
HTML:
slider.htm HTML (1,64 kByte) 19.09.2023 10:21
<!DOCTYPE html >
<html lang="de">
  <head>
    <meta charset="utf-8" />
    <title>Slider/Fader</title>
    <link rel="stylesheet" id="slider.css" href="slider.css" />
  </head>
  <body>
    <h4>horizontal Slider</h4>
    <ul class="slides horizontal ratio44" data-options="thumbs arrows">
      <li data-backgroundimage="/media/IMG_6867.jpg"></li>
      <li data-backgroundimage="/media/IMG_6868.jpg"></li>
      <li data-backgroundimage="/media/IMG_6869.jpg"></li>
      <li data-backgroundimage="/media/IMG_6870.jpg"></li>
      <li data-backgroundimage="/media/IMG_6871.jpg"></li>
      <li data-backgroundimage="/media/IMG_6872.jpg"></li>
    </ul>
    <h4>horizontal Fader</h4>
    <ul class="slides fade horizontal arrows-outside ratio44" data-options="arrows autoplay play_pause">
      <li data-backgroundimage="/media/IMG_6867.jpg"></li>
      <li data-backgroundimage="/media/IMG_6868.jpg"></li>
      <li data-backgroundimage="/media/IMG_6869.jpg"></li>
      <li data-backgroundimage="/media/IMG_6870.jpg"></li>
      <li data-backgroundimage="/media/IMG_6871.jpg"></li>
      <li data-backgroundimage="/media/IMG_6872.jpg"></li>
    </ul>
    <h4>vertical Slider</h4>
    <ul class="slides vertical ratio44" data-options="thumbs arrows autoplay">
      <li data-backgroundimage="/media/IMG_6867.jpg"></li>
      <li data-backgroundimage="/media/IMG_6868.jpg"></li>
      <li data-backgroundimage="/media/IMG_6869.jpg"></li>
      <li data-backgroundimage="/media/IMG_6870.jpg"></li>
      <li data-backgroundimage="/media/IMG_6871.jpg"></li>
      <li data-backgroundimage="/media/IMG_6872.jpg"></li>
    </ul>
    <script src="slider.js"></script>
  </body>
</html>
JavaScript:
slider.js JavaScript (19,26 kByte) 14.02.2024 06:45
// coding: utf-8
/*! Created by: Udo Schmal | https://www.gocher.me/ */
(function() {
  'use strict';

  function Slider(el) {
    var slider = el; // slider div
    slider.setAttribute('aria-roledescription', 'slider');
    if (slider.dataset.title) {
      slider.setAttribute('aria-label', slider.dataset.title);
    }
    var slides = el.querySelector('ul'); // slides ul list
    let language = document.documentElement.lang || 'en';
    let nextTxt, prevTxt, playTxt, pauseTxt, thumbTxt;
    switch (language.substr(0, 2)) {
      case 'de':
        nextTxt = 'Nächster';
        prevTxt = 'Vorheriger';
        playTxt = 'Starten';
        pauseTxt = 'Anhalten';
        thumbTxt = 'Element';
        break;
      default:
        nextTxt = 'Next';
        prevTxt = 'Previous';
        playTxt = 'Play';
        pauseTxt = 'Pause';
        thumbTxt = 'Element';
    }
    if (!slides.classList.contains('slides')) {
      slides.classList.add('slides');
    }
    var items = slides.children; // slides li items
    if (items.length > 1) {
      var controls = null; // bubbles/thumbs ul list
      var controlItems = []; // bubbles/thumbs li items
      var prev = null; // previous div button
      var next = null; // next div button
      var play = null; // play and pause div button
      var active = 0; // active slide position counter
      var slideshow = null;
      var isAuto = true; // is triggered by autoplay event

      // get settings from dom
      var direction = el.classList.contains('vertical') ? 'vertical' : 'horizontal';
      if ((direction == 'horizontal') && !el.classList.contains('horizontal')) {
        el.classList.add('horizontal');
      }
      var fade = el.classList.contains('fade');
      var thumbs = false, bubbles = false, autoplay = false, arrows = false, playpause = false, loop = false;
      if (el.dataset.options) {
        thumbs = el.dataset.options.indexOf('thumbs') !== -1;
        bubbles = el.dataset.options.indexOf('bubbles') !== -1;
        autoplay = el.dataset.options.indexOf('autoplay') !== -1;
        arrows = el.dataset.options.indexOf('arrows') !== -1;
        playpause = el.dataset.options.indexOf('play_pause') !== -1;
        loop = autoplay || playpause || (el.dataset.options.indexOf('loop') !== -1);
      }
      var interval = 3000;
      if (el.dataset.interval) {
        interval = parseInt(el.dataset.interval, 10);
        if (isNaN(interval)) {
          interval = 3000;
        }
      }
      // lazy image loading support
      function setActive (itemId) {
        active = itemId;
        function loadBackground(i) {
          if (items[i].dataset.backgroundimage) {
            items[i].style.backgroundImage = "url('" + items[i].dataset.backgroundimage + "')";
            items[i].removeAttribute('data-backgroundimage');
          }
        }
        loadBackground(active);
        function loadImage(i) {
          let img = items[i].querySelector('img');
          if (img && img.dataset.src) {
            img.src = img.dataset.src;
            img.removeAttribute('data-src');
          }
        }
        loadImage(active);
        let iStart = active - 5;
        let iEnd = active + 5;
        if (iStart < 0) {
          iStart = 0;
        }
        if (iEnd > items.length-1) {
          iEnd = items.length-1;
        }
        for(let i = iStart; i <= iEnd; i++) {
          loadBackground(i);
          loadImage(i);
        }
      }
      for(let i = 0; i < items.length; i++) {
        if (items[i].classList.contains('active')) {
          setActive(i);
        }
        items[i].setAttribute('rol', 'group');
        items[i].setAttribute('aria-roldescription', 'slide');
      }

      function activate (itemId, animated = true) {
        isAuto = true;
        if (fade) {
          // fade in/out
          if (itemId >= items.length) {
            itemId = 0;
          } else if (itemId < 0) {
            itemId = items.length-1;
          }
          for (let i = 0; i < items.length; i++) {
            if (i == itemId) {
              items[i].classList.add('active');
              if (controls) {
                controlItems[i].classList.add('active');
              }
              setActive(i);
            } else {
              items[i].classList.remove('active');
              if (controls) {
                controlItems[i].classList.remove('active');
              }
            }
          }
          if (!loop && arrows) {
              prev.style.display = (itemId == 0) ? 'none' : 'block';
              next.style.display = (itemId == items.length-1) ? 'none' : 'block';
          }
        } else {
          // scroll into parent view
          el = items[itemId];
          if ('scrollBehavior' in document.documentElement.style) {
            if (animated) {
              slides.scrollTo({top: el.offsetTop, left: el.offsetLeft, behavior: 'smooth'});
            } else {
              slides.style.scrollBehavior = 'auto';
              slides.scrollTo(el.offsetLeft, el.offsetTop);
              slides.style.scrollBehavior = '';
            }
          } else {
            slides.style.scrollSnapType = 'none';
            var top = el.offsetTop, left = el.offsetLeft, parent = el.parentNode, attr;
            attr = (direction == 'vertical' ? 'scrollTop' : 'scrollLeft');
            var from = parent[attr] || 0, to = (attr == 'scrollLeft' ? left : top);
            if (from == to) { return; }
            var start = Date.now();
            var tick = function () {
              var t = Math.min(1, ((Date.now() - start) / 1000));
              var eased =  t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1;
              var val = (eased * (to - from)) + from;
              parent[attr] = Math.floor(val);
              if (t<1) {
                window.requestAnimationFrame(tick);
              } else {
                slides.style.scrollSnapType = '';
              }
            };
            tick();
          }
        }
      }

      // add slide and snap scroll event (touch event)
      var scrollTimer;
      function startScroll() {
        if (isAuto) {
          isAuto = false;
        } else {
          if (slideshow) {
            pauseSlideshow();
          }
        }
        for (let i = 0; i < items.length; i++) {
          items[i].classList.remove('active');
          if (items[i].classList.length == 0) {
            items[i].removeAttribute('class');
          }
          if (controls) {
            if (loop) {
              if (i>0 && i<items.length-1) {
                controlItems[i-1].classList.remove('active');
              }
            } else {
              controlItems[i].classList.remove('active');
            }
          }
        }
      }
      function stopScroll() {
        clearTimeout(scrollTimer);
        scrollTimer = null;
        // find new active slide
        let slidesCenter = {
          y: slides.scrollTop + slides.offsetHeight/2,
          x: slides.scrollLeft + slides.offsetWidth/2
        };
        for (let i = 0; i < items.length; i++) {
          if (items[i].offsetTop < slidesCenter.y &&
              items[i].offsetTop + items[i].offsetHeight > slidesCenter.y &&
              items[i].offsetLeft < slidesCenter.x &&
              items[i].offsetLeft + items[i].offsetWidth > slidesCenter.x) {
            let u = i;
            if (loop) {
              if (u == 0) {
                u = items.length-2;
              } else if (u == items.length-1) {
                u = 1;
              }
            }
            if (controls) {
              if (loop) {
                controlItems[u-1].classList.add('active');
              } else {
                controlItems[u].classList.add('active');
              }
            }
            if (!loop && arrows) {
              prev.style.display = (u == 0) ? 'none' : 'block';
              next.style.display = (u == items.length-1) ? 'none' : 'block';
            }
            items[u].classList.add('active');
            if (i != u) {
              isAuto = true;
              slides.style.scrollBehavior = 'auto';
              slides.scrollTo(items[u].offsetLeft, items[u].offsetTop);
              slides.style.scrollBehavior = '';
            }
            setActive(u);
            break;
          }
        }
      }
      function sliderScroll(event) {
        if (scrollTimer) {
          clearTimeout(scrollTimer);
        } else {
          startScroll();
        }
        scrollTimer = setTimeout(stopScroll, 100);
      }
      slides.addEventListener('scroll', sliderScroll);

      function scrollSnapFix() {
        slides.scrollLeft = items[active].offsetLeft;
      }

      // add slideshow
      var restartTimer;
      var startSlideshow = function () {
        if (restartTimer) {
          clearTimeout(restartTimer);
        }
        if (!slideshow) {
          slideshow = setInterval(function () {
            if (active+1 < items.length) {
              activate(++active);
            } else {
              activate(0);
            }
          }, interval);
        }
      }
      this.start = function () {
        if (!slideshow) {
          startSlideshow();
        }
      };
      var stopSlideShow = function () {
        if (slideshow) {
          clearInterval(slideshow);
          slideshow = null;
        }
      }
      this.stop = function () { stopSlideShow(); };
      function pauseSlideshow () {
        if (slideshow) {
          clearInterval(slideshow);
          slideshow = null;
          restartTimer = setTimeout(startSlideshow, 5000);
        };
      }
      function toggleSlideshow (event) {
        if (play.classList.contains('play')) {
          startSlideshow();
          slider.dataset.stop = 'false';
          play.classList.remove('play');
          play.classList.add('pause');
          play.setAttribute('title', pauseTxt);
        } else {
          stopSlideShow();
          slider.dataset.stop = 'true';
          play.classList.remove('pause');
          play.setAttribute('title', pauseTxt);
          play.classList.add('play');
        }
        event.stopPropagation();
      }

      // add play and pause button
      if (playpause) {
        play = document.createElement('button');
        play.setAttribute('type', 'button');
        play.className = autoplay ? 'pause' : 'play';
        play.setAttribute('title', autoplay ? pauseTxt : playTxt);
        play.addEventListener('click', toggleSlideshow);
        el.appendChild(play);
      }

      // add mouse event listeners
      var posInitial, posLast, diff, threshold = 100;
      function dragStart(event) {
        diff = 0;
        event.preventDefault();
        if (direction == 'horizontal') {
          posInitial = slides.scrollLeft;
          posLast = event.clientX;
        } else {
          posInitial = slides.scrollTop;
          posLast = event.clientY;
        }
        slides.style.scrollSnapType = 'none';
        document.addEventListener('mouseup', dragEnd);
        slides.addEventListener('mousemove', dragAction);
      }
      function dragAction(event) {
        if (direction == 'horizontal') {
          diff = diff + (posLast - event.clientX);
          posLast = event.clientX;
          slides.scroll(posInitial + diff, 0);
        } else {
          diff = diff + (posLast - event.clientY);
          posLast = event.clientY;
          slides.scroll(0, posInitial + diff);
        }
      }
      function dragEnd(event) {
        slides.style.scrollSnapType = '';
        if (diff < -threshold) {
          activate(active-1);
        } else if (diff > threshold) {
          activate(active+1);
        } else {
          if (direction == 'horizontal') {
            slides.scroll(posInitial, 0);
          } else {
            slides.scroll(0, posInitial);
          }
        }
        document.removeEventListener('mouseup', dragEnd);
        slides.removeEventListener('mousemove', dragAction);
      }
      slides.addEventListener('mousedown', dragStart, true);

      // add control bubbles/thumbs
      if (bubbles || thumbs) {
        controls = document.createElement('ul');
        controls.classList.add('controls');
        controls.classList.add(thumbs ? 'thumbs' : 'bubbles');
        el.appendChild(controls);
        function controlClick(event) {
          if (autoplay) {
            pauseSlideshow();
          }
          let slide = this.dataset.slide;
          // respect clone slides
          if (!fade && loop) {
            slide++;
          }
          activate(slide);
        }
        for(let i = 0; i < items.length; i++) {
          let li = document.createElement('li');
          li.dataset.slide = i;
          li.setAttribute('tabindex', '0');
          li.setAttribute('role', 'button');
          li.setAttribute('aria-label', thumbTxt + ' ' + (i+1));
          if (thumbs) {
            let file = null;
            if (items[i].dataset.thumbimage) {
              file = items[i].dataset.thumbimage;
            } else if (items[i].dataset.backgroundimage) {
              file = items[i].dataset.backgroundimage;
            } else {
              let img = items[i].querySelector('img');
              if (img) {
                if (img.src && (img.src != 'data:,')) {
                  file = img.src;
                } else if (img.dataset.src) {
                  file = img.dataset.src;
                }
              }
            }
            if (file) {
              // load thumbnails
              //file = file.substr(0, file.lastIndexOf('.')) + '~120' + file.substr(file.lastIndexOf('.'));
              li.style.backgroundImage = "url('" + file + "')";
            }
          }
          li.addEventListener('click', controlClick);
          controls.appendChild(li);
        }
        controlItems = controls.children;
        controlItems[active].classList.add('active');
      }

      // add previous and next button
      function prevClick() {
        if (autoplay) {
          pauseSlideshow();
        }
        activate(active-1);
      }
      function nextClick() {
        if (autoplay) {
          pauseSlideshow();
        }
        activate(active+1);
      }
      if (arrows) {
        prev = document.createElement('button');
        prev.setAttribute('type', 'button');
        prev.className = 'prev';
        prev.setAttribute('title', prevTxt);
        prev.addEventListener('click', prevClick);
        el.appendChild(prev);

        next = document.createElement('button');
        next.setAttribute('type', 'button');
        next.className = 'next';
        next.setAttribute('title', nextTxt);
        next.addEventListener('click', nextClick);
        el.appendChild(next);
      }

      if (fade || !loop) {
        if (arrows && !loop) {
          prev.style.display = 'none';
        }
      } else {
        // clone slides
        slides.appendChild(items[0].cloneNode(true));
        slides.insertBefore(items[items.length-2].cloneNode(true), items[0]);
        items[0].classList.add('clone');
        items[items.length-1].classList.add('clone');
        // remove links for popup
        let link = items[0].querySelector('a.hires');
        if (link) {
          items[0].insertBefore(link.querySelector('figure'), link);
          items[0].removeChild(link);
        }
        link = items[items.length-1].querySelector('a.hires');
        if (link) {
          items[items.length-1].insertBefore(link.querySelector('figure'), link);
          items[items.length-1].removeChild(link);
        }
        // goto first slider item
        if (direction == 'vertical') {
          slides.scrollTo(0, slides.offsetHeight);
        } else {
          slides.scrollTo(slides.offsetWidth, 0);
        }
        setActive(active+1);
      }
      activate(active, false);
      if (autoplay) {
        startSlideshow();
      }
      // accessibility: keydown event
      function keydown (event) {
        switch (event.key) {
          case 'ArrowLeft':
          case 'ArrowUp':
            prevClick();
            event.preventDefault();
            break;
          case 'ArrowRight':
          case 'ArrowDown':
            nextClick();
            event.preventDefault();
            break;
          case 'Enter':
          case ' ':
            let rol = event.target.getAttribute('role');
            if (rol === 'button') {
              event.target.click();
              event.preventDefault();
            }
            break;
        }
      }
      slider.addEventListener('keydown', keydown);
      slides.setAttribute('tabindex', '0');
      slides.addEventListener('keydown', keydown);
      window.addEventListener('resize', scrollSnapFix);
    } else {
      if (items[0].dataset.backgroundimage) {
        items[0].style.backgroundImage = "url('" + items[0].dataset.backgroundimage + "')";
        items[0].removeAttribute('data-backgroundimage');
      }
      let img = items[0].querySelector('img');
      if (img && img.dataset.src) {
        img.src = img.dataset.src;
        img.removeAttribute('data-src');
      }
    }
  }

  var els = document.querySelectorAll('.slides'), cnt = els.length, i;
  if (els.length > 0) {
    // load stylesheet if not already loaded
    if (!document.getElementById('slider.css')) {
      var style = document.createElement("link");
      style.type = 'text/css';
      style.addEventListener('load', function () {
        init();
      });
      style.href = '/code/slider/slider.css';
      style.id = 'slider.css';
      style.rel = 'stylesheet';
      document.head.appendChild(style);
    } else {
      init();
    }
    function init () {
      console.log('slider: Slider lazy loading by IntersectionObserver');
      // only show and do autoplay interval if slider is in viewport
      function loadSlider(el, start) {
        if (el.obj) {
          if (el.querySelectorAll('ul.slides li').length > 1) {
            if (start) {
              el.obj.start();
            } else {
              el.obj.stop();
            }
          }
        } else {
          el.obj = new Slider(el);
        }
      }
      // create intersection observer
      let lazyobserver = new IntersectionObserver(function(entries, observer) {
        for (var i=0; i < entries.length; i++) {
          if (entries[i].isIntersecting) {
            if (entries[i].target.dataset.options.indexOf('autoplay') !== -1) {
              if (entries[i].target.dataset.stop && entries[i].target.dataset.stop === 'true') {
                //loadSlider(entries[i].target, false);
              } else {
                loadSlider(entries[i].target, true);
              }
            } else {
              loadSlider(entries[i].target, false);
              lazyobserver.unobserve(entries[i].target);
            }
          } else {
            loadSlider(entries[i].target, false);
          }
        }
      }, {});
      // start observing
      for (var i=0; i < els.length; i++) {
        let slides = els[i];
        let slider = document.createElement('div');
        slider.className = slides.className; // move all classes
        slider.classList.remove('slides');
        slider.classList.add('slider');
        slides.className = 'slides'; // remove all other classes
        slider.dataset.options = slides.dataset.options;
        slides.removeAttribute('data-options');
        if (slides.dataset.title) {
          slider.dataset.title = slides.dataset.title;
        }
        slides.parentNode.insertBefore(slider, slides);
        slider.appendChild(slides);
        lazyobserver.observe(slider);
      }
    }
  }

  // expose constructor globally
  window.Slider = Slider;
})();
StyleSheet:
slider.css StyleSheet (6,61 kByte) 28.02.2024 21:10
/* coding: utf-8 */
@media screen {
.slider {
  position: relative;
  width: 100%;
}
.overlay .slider {
  position: initial;
}
/* slider with ratio 44% */
.slider.ratio44 {
  height: 0;
  min-height: 1px;
  padding-top: 44%;
}
.slider.horizontal {
  overflow-y: clip;
  overflow-x: visible;
}
.slider.vertical {
  overflow-x: clip;
  overflow-y: visible;
}
.slider.horizontal.arrows-outside {
  margin: 0 auto;
  width: calc(100% - 100px);
}
.slider.vertical.arrows-outside {
  margin: auto 0;
  height: calc(100% - 100px);
}
.slider > .slides {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 0;
  list-style-type: none;
  /*overflow-scrolling: auto;*/
  /* hide IE and old Edge scrollbar */
  -ms-overflow-style: none;
  /* hide Firefox scrollbar */
  scrollbar-width: none;
}
/* hide Chrome, Safari and Opoera (WebKit) scrollbar */
.slider > .slides::-webkit-scrollbar {
  display: none;
}
.slider.horizontal > .slides {
  bottom: -12px; /* scrollbar fix */
  display: flex;
  scroll-snap-type: x mandatory;
  -ms-scroll-snap-type: x mandatory;
  overflow-x: scroll;
  overflow-y: hidden;
}
.slider.vertical > .slides {
  right: -12px; /* scrollbar fix */
  scroll-snap-type: y mandatory;
  -ms-scroll-snap-type: y mandatory;
  overflow-y: scroll;
  overflow-x: hidden;
}
.slider .slides > li {
  position: relative;
  margin: 0;
  padding: 0;
  scroll-snap-align: start;
  /* for background-image */
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
}
.slider.contain .slides > li {
  background-size: contain;
}
.slider.horizontal .slides > li {
  width: 100%;
  height: auto;
  display: inline-block;
  flex-shrink: 0;
}
.slider.vertical > .slides > li {
  height: 100%;
  width: auto;
}
.slider.fade > .slides > li {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 0;
  visibility: hidden;
  opacity: 0;
  transition: visibility 3s linear,opacity 3s linear;
}
.slider.fade > .slides > li:first-child {
  z-index: 1;
}
.slider.fade > .slides > li.active {
  visibility: visible;
  opacity: 1;
  transition: visibility 3s linear,opacity 3s linear;
}
.slider.fade > .controls, .slider.fade > button {
  z-index: 2;
}

.slider > .slides > li figure img {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
}

/* centered slider content */
.slider > .slides > li.centered img {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  max-width: 90%;
  max-height: 90%;
}
.slider > .slides > li > p {
  position: absolute;
  left: 50%;
  bottom: 15px;
  transform: translateX(-50%);
  color: #fff;
}

.slider > .controls {
  margin: 0;
  padding: 0;
}
.slider.horizontal > .controls {
  position: absolute;
  right: 0;
  left: 0;
  bottom: 5%;
  text-align: center;
}
.slider.vertical > .controls {
  position: absolute;
  top: 50%;
  right: 2%;
  transform: translate(0, -50%);
  display: block;
}
.slider.vertical > .controls::after {
  display: table;
  content: '';
  clear: both;
}
.slider.horizontal > .controls.thumbs {
  height: 10%;
}
.slider.vertical > .controls.thumbs {
  width: 10%;
}
.slider > .controls > li {
  display: inline-block;
  outline: none;
  background-color: #fff;
  opacity: 0.8;
  cursor: pointer;
  z-index: 2;
}
.slider > .controls > li:focus-visible  {
  outline: 2px dotted #F84500;
}
.slider.horizontal > .controls > li {
  display: inline-block;
  margin: 0 5px;
}
.slider.vertical > .controls > li {
  display: block;
  margin: 5px 0;
}

.slider > .controls.bubbles > li {
  border: 1px solid #000;
  transition: border 500ms ease-out;
  width: 0.85em;
  height: 0.85em;
  border-radius: 50%;
}
.slider > .controls.thumbs > li {
  border: 2px solid #000;
  transition: border 500ms ease-out;
}
.slider > .controls.bubbles > li.active {
  background-color: #000;
}
.slider > .controls.thumbs > li.active {
  border-color: #fff;
}
.slider > .controls.thumbs > li {
  position: relative;
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
}
.slider.horizontal > .controls.thumbs > li {
  width: 10%;
  height: 100%;
}
.slider.vertical > .controls.thumbs > li {
  padding-top: 44%;
  width: 100%;
}

.slider > .prev, .slider > .next {
  cursor: pointer;
  position: absolute;
  text-shadow: 1px 1px 1px #000;
  background: none;
  border: none;
}
.slider.horizontal > .prev, .slider.horizontal > .next {
  top: 50%;
  transform: translate(0, -50%);
}
.slider.vertical > .prev, .slider.vertical > .next {
  left: 50%;
  transform: translate(-50%, 0);
}
.slider.horizontal > .prev {
  left: 15px;
}
.slider.horizontal.arrows-outside > .prev {
  left: -35px;
}
.slider.horizontal > .next {
  right: 15px;
}
.slider.horizontal.arrows-outside > .next {
  right: -35px;
}
.slider.vertical > .prev {
  top: 15px;
}
.slider.vertical.arrows-outside > .prev {
  top: -35px;
}
.slider.vertical > .next {
  bottom: 15px;
}
.slider.vertical.arrows-outside > .next {
  bottom: -35px;
}

.slider.arrows-outside > .prev::after, .slider.arrows-outside > .next::after {
  color: #000;
}

.slider > .prev.hidden, .slider > .next.hidden {
  display: none;
}
.slider > .prev::after, .slider > .next::after, .slider > .play::after, .slider > .pause::after {
  display: inline-block;
  color: #fff;
  font-size: 2em;
}
.slider > .prev::after, .slider > .next::after {
  border: solid white;
  border-width: 0 3px 3px 0;
  padding: 12px;
  content: ' ';
  box-shadow: 5px 5px 0px 0px rgba(0, 0, 0, 0.5);
}
.slider.horizontal > .prev::after {
  transform: rotate(135deg);
  margin: 6px 0 6px 12px;
}
.slider.horizontal > .next::after {
  transform: rotate(-45deg);
  margin: 6px 12px 6px 0;
}
.slider.vertical > .prev::after {
  transform: rotate(-135deg);
  margin: 12px 6px 0 6px;
}
.slider.vertical > .next::after {
  transform: rotate(45deg);
  margin: 0 6px 12px 6px;
}

.slider > .play, .slider > .pause {
  border-radius: 50% / 10%;
  color: #fff;
  font-size: 2em;
  height: 1.5em;
  width: 2em;
  position: absolute;
  bottom: 10px;
  left: 50%;
  transform: translateX(-50%);
  cursor: pointer;
  background: red;
  border: none;
  z-index: 3;
}
.slider .play::before, .slider > .pause::before  {
  background: inherit;
  border-radius: 5% / 50%;
  bottom: 9%;
  content: "";
  left: -5%;
  position: absolute;
  right: -5%;
  top: 9%;
}
.slider > .play::after, .slider > .pause::after {
  color: rgba(255, 255, 255, 0.75);
  font-size: 1em;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.slider > .play::after {
  top: 45%;
  content: "\25B6";
}
.slider > .pause::after {
  content: "\2161";
  font-weight: bold;
}
}

Kontakt

Udo Schmal
Udo Schmal

Udo Schmal
Softwareentwickler
Ellerndiek 26
24837 Schleswig
Schleswig-Holstein
Germany




+49 4621 9785538
+49 1575 0663676
+49 4621 9785539
SMS
WhatsApp

Google Maps Profile
Instagram Profile
vCard 2.1, vCard 3.0, vCard 4.0

Service Infos

CMS Info

Product Name:
UDOs Webserver
Version:
0.5.1.81
Description:
All in one Webserver
Copyright:
Udo Schmal
Compilation:
Mon, 15. Apr 2024 18:45:24

Development Info

Compiler:
Free Pascal FPC 3.3.1
compiled for:
OS:Linux, CPU:x86_64

System Info

OS:
Ubuntu 22.04.4 LTS (Jammy Jellyfish)

Hardware Info

Model:
Hewlett-Packard HP Pavilion dm4 Notebook PC
CPU Name:
Intel(R) Core(TM) i5-2430M CPU @ 2.40GHz
CPU Type:
x86_64, 1 physical CPU(s), 2 Core(s), 4 logical CPU(s),  MHz