Experiment: JavaScript Boxed Carousel with Progress Indicator

on in JavaScript Carousels
Last modified on

Here’s an awesome JavaScript carousel built for a client project, but then scrapped. It definitely has potential for unlimited items.

Currently, it has a 5-second delay between slides and a neat progress indicator.

Vanilla JavaScript Boxed Carousel
Vanilla JavaScript Boxed Carousel

See the Pen Experiment: Boxed Carousel by Ciprian (@ciprian) on CodePen.

HTML Code

<ol class="s1-slider s1-slider--active-1">
    <li class="s1-slider__item s1-slider__item--1 ui-dark is-active" data-active="1">
        <div class="s1-slider__item__wrapper">
            <div class="s1-slider__item__text">
                <h2>Mark Haddon</h2>
                <p>Reading is a conversation. All books talk. But a good book listens as well.</p>
                <p><a href="#">Learn more</a></p>
            </div>
        </div>
    </li>
    <li class="s1-slider__item s1-slider__item--2 ui-primary" data-active="2">
        <div class="s1-slider__item__wrapper">
            <div class="s1-slider__item__text">
                <h2>Paul Sweeney</h2>
                <p>You turn the last page and feel a little as if you have lost a friend.</p>
                <p><a href="#">Learn more</a></p>
            </div>
        </div>
    </li>
    <li class="s1-slider__item s1-slider__item--3 ui-light" data-active="3">
        <div class="s1-slider__item__wrapper">
            <div class="s1-slider__item__text">
                <h2>Celeste Ng</h2>
                <p>The story is truly finished when the reader enters.</p>
                <p><a href="#">Learn more</a></p>
            </div>
        </div>
    </li>
</ol>

CSS

ol {
    margin: 0;
    padding: 0;
}
ol li {
    margin: 0;
    list-style: none;
}

.s1-slider__item__text h2 {
    font-weight: 400;
    color: #000;
}
.form-control-range__handle p,
.s1-slider__item__text p {
    font-size: 18px;
    line-height: 1.25;
}

.s1-slider__item__text a {
    font-size: 14px;
    background-color: #000000;
    color: #ffffff;
    padding: 12px 24px;
    display: inline-block;
    text-decoration: none;
}

.s1-slider__item__text h2 {
    font-size: 20px;
    line-height: 1.5;
    margin-top: 0;
}
.s1-slider__item:before {
    font-size: 0.8rem;
    line-height: 2em;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.s1-slider {
    font-weight: 300;
    counter-reset: slider;
    position: absolute;
    z-index: 10;
    margin: 0;
    width: 21.05263vw;
    height: 21.05263vw;
    right: 48px;
    bottom: 48px;
    transition-timing-function: cubic-bezier(0.55, 0, 0.1, 1);
    transition-duration: 0.9s;
    transition-property: transform;
}
.s1-slider--active-2 {
    transform: translateY(-21.05263vw);
}
.s1-slider--active-3 {
    transform: translate(-21.05263vw, -21.05263vw);
}

.s1-slider__item {
    counter-increment: slider;
    position: absolute;
    cursor: pointer;
    width: 31.57895vw;
    height: 31.57895vw;
    transition-timing-function: cubic-bezier(0.55, 0, 0.1, 1);
    transition-duration: 0.9s;
    transition-property: transform;
    transform: scale(0.33333);
}
.s1-slider__item__wrapper {
    position: relative;
    overflow: hidden;
    width: 31.57895vw;
    height: 31.57895vw;
}
.s1-slider__item__wrapper:before {
    content: "";
    position: absolute;
    left: -5%;
    top: -5%;
    width: 110%;
    height: 110%;
}

.s1-slider__item--1 .s1-slider__item__wrapper:before {
    background: #ffffff;
}
.s1-slider__item--2 .s1-slider__item__wrapper:before {
    background: #546de5;
}
.s1-slider__item--3 .s1-slider__item__wrapper:before {
    background: #c44569;
}

.s1-slider__item--1 .s1-slider__item__text h2,
.s1-slider__item--1 .s1-slider__item__text p {
    color: #000000;
}
.s1-slider__item--2 .s1-slider__item__text h2,
.s1-slider__item--2 .s1-slider__item__text p {
    color: #ffffff;
}
.s1-slider__item--3 .s1-slider__item__text h2,
.s1-slider__item--3 .s1-slider__item__text p {
    color: #ffffff;
}

.s1-slider__item--1:before {
    color: #000000;
}
.s1-slider__item--1:after {
    color: #ffffff;
}
.s1-slider__item--2:after {
    color: #ffffff;
}
.s1-slider__item--3:after {
    color: #ffffff;
}

.s1-slider__item a {
    pointer-events: none;
}
.s1-slider__item.is-active a {
    pointer-events: all;
}
.s1-slider__item.is-active {
    cursor: default;
    transform: scale(1);
}
.s1-slider__item--1 {
    right: 10.52632vw;
    bottom: 10.52632vw;
    transform-origin: 100% 100%;
    z-index: 1;
}
.s1-slider--active-3 .s1-slider__item--1 {
    transform: scale(0.33333) translateX(100%);
}
.s1-slider__item--2 {
    right: 10.52632vw;
    top: 10.52632vw;
    transform-origin: 100% 0;
}
.s1-slider__item--3 {
    left: 10.52632vw;
    top: 10.52632vw;
    transform-origin: 0 0;
}
.s1-slider--active-1 .s1-slider__item--3 {
    transform: scale(0.33333) translateY(-100%);
}
.s1-slider__item:before {
    content: "0" counter(slider);
    position: absolute;
    z-index: 1;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%) scale(3);
    transition-timing-function: cubic-bezier(0.55, 0, 0.1, 1);
    transition-duration: 0.6s;
    transition-property: opacity;
}
.s1-slider__item.is-active:before {
    opacity: 0;
}
.s1-slider__item__text {
    position: relative;
    padding: 32px;
    transition-timing-function: cubic-bezier(0.55, 0, 0.1, 1);
    transition-duration: 0.9s;
    transition-property: transform, opacity;
    transition-delay: 0ms, 0.15s;
    opacity: 0;
}
.s1-slider__item--1 .s1-slider__item__text {
    color: #ffffff;
    transform-origin: 100% 100%;
    transform: scale(2) translate(100%, 100%);
}
.s1-slider__item--2 .s1-slider__item__text {
    transform-origin: 100% 0;
    transform: scale(2) translate(100%, -100%);
}
.s1-slider__item--3 .s1-slider__item__text {
    transform-origin: 0 0;
    transform: scale(2) translate(-100%, -100%);
}
.s1-slider__item.is-active .s1-slider__item__text {
    transform: scale(1);
    opacity: 1;
}

.s1-text {
    position: absolute;
    z-index: 1;
    left: 6.25vw;
    top: 6.25vw;
    margin: 0;
    color: #fff;
    font-size: 1.2rem;
    line-height: 1.25em;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.s1-slider__item.is-active .s1-slider__item__text {
    position: relative;
}
.s1-slider__item.is-active .s1-slider__item__text:before {
    content: "";
    position: absolute;
    top: 0%;
    left: 0;
    height: 3px;
    z-index: 2;
    background-color: #000000;

    animation: 5s linear slider--interval;
}

@keyframes slider--interval {
    from {
        right: 100%;
    }
    to {
        right: 0%;
    }
}

JavaScript

document.addEventListener("DOMContentLoaded", function () {
    [].forEach.call(
        document.querySelectorAll(".s1-slider .s1-slider__item"),
        function (sliderItem) {
            sliderItem.addEventListener("click", function (event) {
                document
                    .querySelector(".s1-slider")
                    .classList.remove("s1-slider--active-1");
                document
                    .querySelector(".s1-slider")
                    .classList.remove("s1-slider--active-2");
                document
                    .querySelector(".s1-slider")
                    .classList.remove("s1-slider--active-3");

                document
                    .querySelector(".s1-slider")
                    .classList.add(
                        "s1-slider--active-" + sliderItem.dataset.active
                    );

                Array.from(
                    document.getElementsByClassName("s1-slider__item is-active")
                ).forEach((el) => el.classList.remove("is-active"));

                sliderItem.classList.add("is-active");
            });
        }
    );

    const slideArray = [
        ".s1-slider__item--1",
        ".s1-slider__item--2",
        ".s1-slider__item--3"
    ];

    let slideLoop = function (i) {
        if (slideArray[i]) {
            setTimeout(function () {
                i = i === 2 ? -1 : i;
                console.log(i);
                slideLoop(i + 1);
                document
                    .querySelector(".s1-slider " + slideArray[i + 1])
                    .click();
            }, 5000);
        }
    };
    slideLoop(0);
});

Related posts