Slider [concept]

by Konstantin Rouda

HTML

<header>

  <section class="c-slider jsSlider" data-active-slide="1">
  
    <header class="c-slider__header">
    
      <section class="c-slider__images jsImages">
        <img src="https://c1.staticflickr.com/5/4245/34636588783_a680206a43_o.png" class="is-active" width="640" height="448" alt="smile">
        <img src="https://c1.staticflickr.com/5/4264/35059249620_f0b1ab705b_o.png" width="564" height="640" alt="dream" />
        <img src="https://c1.staticflickr.com/5/4232/35316458451_3237db0c7b_o.png" width="640" height="477" alt="be-brave" />
        <img src="https://c1.staticflickr.com/5/4258/34636590613_741117d1d8_o.png" width="640" height="618" alt="just-love" />
      </section>

      
      <section class="c-slider__bgs jsBgs">
        <div class="c-slider__bg is-active" data-slide="1"></div>
        <div class="c-slider__bg" data-slide="2"></div>
        <div class="c-slider__bg" data-slide="3"></div>
      </section>
      
      
      <div class="c-slider__nav-btn c-slider__nav-btn--next jsSliderNavBtn"  data-direction="forward">
      
        <div class="c-slider__arrow c-slider__arrow--next"></div>
        
      </div>
      
      <div class="c-slider__nav-btn c-slider__nav-btn--prev jsSliderNavBtn"  data-direction="backward">
          
        <div class="c-slider__arrow c-slider__arrow--prev"></div>
        
      </div>
      

      <!--Dots-->
      <section class="c-slider-dots jsDots">
        <div class="c-slider__dot is-active" data-slide="1">
          <input type="radio" class="c-slider__dot-input h-sr-only" name="slider-dot" id="slide1" checked />
          <label for="slide1" class="c-slider__dot-label jsLabel"></label>
        </div>
        
        <div class="c-slider__dot" data-slide="2">
          <input type="radio" class="c-slider__dot-input h-sr-only" name="slider-dot" id="slide2" />
          <label for="slide2" class="c-slider__dot-label jsLabel"></label>
        </div>
        
        <div class="c-slider__dot"...

CSS

HTML {
  font-size: 150%;
  line-height: 1.5;
  box-sizing: border-box;
}

BODY {
  color: rgb(64, 69, 71);
  margin: 0;
}

*, *::before, *::after {
  box-sizing: inherit;
  color: inherit;
}


HEADER { margin: 0; padding: 0.01rem; }

IMG { max-width: 100%; }

/*Actual Style*/

  /*============
     C-Slider
  ==============*/
.c-slider {
  width: 100%;
  min-height: 100vh;
  margin: 0;
}

  /*=================
     C-Slider-Header
  ===================*/

.c-slider__header {
  position: relative;
  min-height: 40vh;
  background-color: rgb(164, 158, 155); /*fallback*/
  background-image: linear-gradient(135deg, rgb(164, 158, 155),rgb(212, 209, 207));
}


[data-active-slide="1"] .c-slider__bg[data-slide="1"],
[data-active-slide="1"] .c-slider__nav-btn, 
.c-slider__dot[data-slide="1"] .c-slider__dot-label {
  background: linear-gradient(135deg, rgb(164, 158, 155),rgb(212, 209, 207));
}

[data-active-slide="2"] .c-slider__bg[data-slide="2"],
[data-active-slide="2"] .c-slider__nav-btn, 
.c-slider__dot[data-slide="2"] .c-slider__dot-label {
  background: linear-gradient(135deg,rgb(0, 89, 117),rgb(6, 180, 193));
}

[data-active-slide="3"] .c-slider__bg[data-slide="3"],
[data-active-slide="3"] .c-slider__nav-btn, 
.c-slider__dot[data-slide="3"] .c-slider__dot-label {
  background: linear-gradient(135deg,rgb(251, 146, 14),rgb(222, 93, 54));
}


  /*=================
     C-Slider-Images
  ===================*/

.c-slider__images {
  position: relative;
} 

.c-slider__images > IMG {
  position: absolute;
  left: 50%;
  transform: translate(-50%, 30%);
  opacity: 0;
  visibility: hidden;
  z-index: 2;
  transition: opacity .5s .3s ease, visibility 0s .2s linear;
}

.c-slider__images .is-active {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

  /*=================
     C-Slider-Bgs
  ===================*/

.c-slider__bgs {
}

.c-slider__bg {
  position: absolute;
  left: 0; top: 0;
  width: 100%; height: 100%;
  opacity: 0;
  transition: opacity .5s...

JavaScript

;(function() {
  "use strict";
  
  const slider = document.querySelector(".jsSlider");
  const imgs = Array.from(slider.querySelector(".jsImages").children);
  const bgs = Array.from(slider.querySelector(".jsBgs").children);
  const sliderNavBtns = slider.querySelectorAll(".jsSliderNavBtn");
  const dotsContainer = slider.querySelector(".jsDots");
  const radioBtns = dotsContainer.querySelectorAll("[type=radio]");
  const dots = Array.from(dotsContainer.children);
  
  const DOT_CLASS_IDENTIFIER = "jsLabel";
  const SLIDER_ANIMATION_CLASS = "is--animated";
  const ACTIVE_DOTS_CLASS = "is-active";
  const ACTIVE_BGS_CLASS = "is-active";
  const ACTIVE_IMGS_CLASS = "is-active";
   
  const BTN_NEXT_DIRECTION = "forward";
  const BTN_PREV_DIRECTION = "backward";
  const BTN_DIRECTION_ATTR_NAME = "data-direction";
  const SLIDE_ATTR_NAME = "data-slide";
  const ITEM_SLIDE_PROP_NAME = "dataSlide";
  const SLIDER_ACTIVE_SLIDE_ATTR = "data-active-slide";
  
  let currentActiveSlideNum = 1;
  const maxSlidesNum = dots.length;
  
  /*pre-execution actions*/
  setPropertyFromAttribute(dots, SLIDE_ATTR_NAME, ITEM_SLIDE_PROP_NAME, false);
  setPropertyFromAttribute(bgs, SLIDE_ATTR_NAME, ITEM_SLIDE_PROP_NAME, false);

   
  /*=======================
    Adding Eventlisteners
  =========================*/
  sliderNavBtns.forEach(function(v) {
    v.addEventListener("click", navBtnOnClick);
    v.direction = v.getAttribute(BTN_DIRECTION_ATTR_NAME);
  });
  
  sliderNavBtns[0].addEventListener("animationend", navBtnOnAnimationEnd);
  
  dotsContainer.addEventListener("click", dotsOnClick, true);
   
  /*=======================
       Eventlisteners
  =========================*/
   
  function dotsOnClick(e) {
    const current = e.target;
    /*capture click only for element with specified class*/
    if(!current.classList.contains(DOT_CLASS_IDENTIFIER)) return;
    
    currentActiveSlideNum = parseInt(current.parentElement[ITEM_SLIDE_PROP_NAME]);
    
   ...