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]);
...