<!-- www.oakdigital.dk -->

<div class="oakslider">
  
    <div class="oakslider__ui">
        <div class="oakslider__nav">
            <div class="oakslider__navpoint">01 <div class="oakslider__timer"><div class="timer__progress"></div></div> <span class="oakslider__label">Oak Lab Case Story</span></div>
            <div class="oakslider__navpoint">02 <div class="oakslider__timer"><div class="timer__progress"></div></div> <span class="oakslider__label">Oak Lab Case Story</span></div>
            <div class="oakslider__navpoint">03 <div class="oakslider__timer"><div class="timer__progress"></div></div> <span class="oakslider__label">Oak Lab Case Story</span></div>
        </div>
        <div class="oakslider__controls">
            <div class="oakslider__arrow oakslider__arrow--left oakslider__prev"><</div>
            <div class="oakslider__arrow oakslider__arrow--right oakslider__next">></div>
        </div>
    </div>

    <div class="oakslider__slider">
        <div class="oakslider__slide slide--active" data-slide="1">
            <div class="slide__image"><img src="https://dbpadventures.kinsta.cloud/wp-content/uploads/2020/04/ngor-senegal-dronebillede.jpg" alt=""></div>
            <div class="slide__container">
                <div class="slide__content">
                    <div class="slide__title">The quick brown fox jumps <span class="text--highlight">over the lazy dog</span></div>
                    <div class="slide__link">Learn more about their approach</div>
                </div>
            </div>
        </div>
        <div class="oakslider__slide" data-slide="2">
            <div class="slide__image"><img src="https://dbpadventures.kinsta.cloud/wp-content/uploads/2020/04/ngor-island-drone.jpg" alt=""></div>
            <div class="slide__container">
                <div class="slide__content">
                    <div class="slide__title">The quick brown fox jumps <span class="text--highlight">over the lazy dog</span></div>
                    <div class="slide__link">Learn more about their approach</div>
                </div>
            </div>
        </div>
        <div class="oakslider__slide" data-slide="3">
            <div class="slide__image"><img src="https://dbpadventures.kinsta.cloud/wp-content/uploads/2020/04/strand-ngor-senegal.jpg" alt=""></div>
            <div class="slide__container">
                <div class="slide__content">
                    <div class="slide__title">The quick brown fox jumps <span class="text--highlight">over the lazy dog</span></div>
                    <div class="slide__link">Learn more about their approach</div>
                </div>
            </div>
        </div>
    </div>
</div>
/* www.oakdigital.dk */

body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}

.oakslider {
    position: relative;
    top: 0;
    left: 0;
    width: 100%;
    min-height: 100vh;
    background: #22273C;
    color: #fff;
    display: flex;
    align-items: flex-start;
    overflow: hidden;
}


.oakslider__ui {
    position: relative;
    z-index: 2;

    max-width: 1200px;
    min-width: 60%;
    margin: 0 auto;
    margin-top: 10%;
    display: flex;
    justify-content: space-between;

    .oakslider__controls {
        display: flex;
    }

    .oakslider__arrow {
        width: 50px;
        height: 50px;
        border-radius: 100%;
        border: 1px solid #fff;
        opacity: 0.5;
        background: #fff;
        margin-left: 20px;
        display: flex;
        justify-content: center;
        align-items: center;
        color: black;
    }
    
}

.oakslider__navpoint {
    display: flex;
    align-items: center;
    margin-bottom: 10px;
    font-weight: 900;

    &:first-of-type {
        .oakslider__timer {
            width: 95px;
        }
        .oakslider__label {
            opacity: 1;
        }
    }

    .oakslider__label {
        opacity: 0;
        font-weight: 400;
    }

    .oakslider__timer {
        position: relative;
        width: 55px;
        height: 1px;
        background: rgba(#fff, 0.5);
        margin: 0 5px;
        overflow: hidden;

        .timer__progress {
            position: absolute;
            top: 0;
            left: 0;
            background: #fff;
            height: 1px;
            width: 100%;
            transform: translateX(-100%);
        }
    }
}

.oakslider__slide {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    display: none;

    &.slide--active {
        display: block;
    }
}

.slide__image {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;

    img {
        position: absolute;
        object-fit: cover;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        opacity: .5;
    }
}

.slide__container {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.slide__content {
    padding-top: 100px;
    max-width: 1200px;
    min-width: 60%;
    font-family: sans-serif;
}

.slide__title {
    font-size: 45px;
    max-width: 650px;
    line-height: 1.2;
    font-weight: 600;
}

.slide__link {
    margin-top: 25px;
}
View Compiled
/* www.oakdigital.dk */

var oakSlider = {

    /*------------------------------------------------
    # Slider Settings
    ------------------------------------------------*/
    settings: {
        currentSlide: 1,
        totalSlides: 0,
        animating: false,
        autoPlay: true,
        autoPlaySpeed: 8, // Increase to stay on slides for longer
        transitionSpeed: 2.75, // Changes transition speed
        autoPlayInterval: false,
        ease: 'expo',
        timeline: gsap.timeline({}),
        imageScale: '',
        controls: {
            next: document.querySelector('.oakslider__next'),
            prev: document.querySelector('.oakslider__prev'),
            nav: document.querySelectorAll('.oakslider__navpoint'),
        }
    },

    /*------------------------------------------------
    # Initiate Slider
    ------------------------------------------------*/
    init: function() {
        this.settings.totalSlides = document.querySelectorAll('.oakslider__slide').length;
        this.settings.controls.prev.addEventListener('click', () => { this.stopAutoPlay(); this.changeSlide('prev'); });
        this.settings.controls.next.addEventListener('click', () => { this.stopAutoPlay(); this.changeSlide('next'); });
        this.settings.controls.nav.forEach((el, key) => {
            el.addEventListener('click', () => { this.stopAutoPlay(); this.jumpToSlide(key + 1); });
        });

        this.settings.imageScale = gsap.to('.slide--active .slide__image img', 15, {scale: 1.1, ease: "sine.inOut", yoyo:true, yoyoEase: true, repeat: -1});

        if(this.settings.autoPlay) {
            this.autoPlay();
        }
    },

    /*------------------------------------------------
    # Change Slide
    ------------------------------------------------*/
    changeSlide: function( dir ) {
        console.log(this.settings.animating);
        if(this.settings.animating) return;
        let animateFrom = this.settings.currentSlide;
        if(dir === 'next') {
            if(this.settings.currentSlide >= this.settings.totalSlides) {
                this.settings.currentSlide = 1;
            } else {
                this.settings.currentSlide++;
            }
        } else {
            if(this.settings.currentSlide <= 1) {
                this.settings.currentSlide = this.settings.totalSlides;
            } else {
                this.settings.currentSlide--;
            }
        }
        this.slideAnimation(animateFrom, this.settings.currentSlide, dir);
    },

    /*------------------------------------------------
    # Slide Navigation
    ------------------------------------------------*/
    jumpToSlide: function(slide) {
        if(this.settings.animating || slide === this.settings.currentSlide) return;
        let animateFrom = this.settings.currentSlide;
        this.settings.currentSlide = slide;
        if(slide > animateFrom) {
            dir = 'next';
        } else {
            dir = 'prev';
        }

        this.slideAnimation(animateFrom, this.settings.currentSlide, dir);
    },

    /*------------------------------------------------
    # Autoplaying
    ------------------------------------------------*/
    autoPlay: function() {
        this.settings.autoPlay = true;

        let el = this.settings.controls.nav[this.settings.currentSlide - 1].children[0].children[0];
        this.settings.timeline.fromTo(el, this.settings.autoPlaySpeed - this.settings.transitionSpeed, {
            x: '-100%'
        }, {
            x: 0,
            ease: 'none',
            delay: 0.5,
            onComplete: () => {
                this.changeSlide('next');
            }
        });
    },

    stopAutoPlay: function() {
        if(this.settings.autoPlay) {
            this.settings.timeline.progress(100);
        }
        this.settings.autoPlay = false;
    },

    /*------------------------------------------------
    # Update Nav
    ------------------------------------------------*/
    updateNav: function(from, to) {
        gsap.to(this.settings.controls.nav[from - 1].children[0], this.settings.transitionSpeed, {
            width: 55,
            ease: this.settings.ease + '.inOut',
        });
        gsap.to(this.settings.controls.nav[from - 1].children[1], this.settings.transitionSpeed, {
            opacity: 0,
            ease: this.settings.ease + '.inOut',
        });
        gsap.to(this.settings.controls.nav[to - 1].children[0], this.settings.transitionSpeed, {
            width: 95,
            ease: this.settings.ease + '.inOut',
        });
        gsap.to(this.settings.controls.nav[to - 1].children[1], this.settings.transitionSpeed, {
            opacity: 1,
            ease: this.settings.ease + '.inOut',
        });
        gsap.to(this.settings.controls.nav[from - 1].children[0].children[0], this.settings.transitionSpeed, {
            x: '100%',
            ease: this.settings.ease + '.inOut'
        });
    },

    /*------------------------------------------------
    # Slide Animation
    ------------------------------------------------*/
    slideAnimation: function(from, to, dir) {
        this.settings.animating = true;

        console.log(this.settings.animating);

        this.updateNav(from, to);

        from = '.oakslider__slide[data-slide="' + from + '"]';
        to   = '.oakslider__slide[data-slide="' + to + '"]';

        this.settings.timeline.clear();
        this.settings.timeline.play(0);

        this.settings.timeline.set(to, {display: 'block',})
        .to(from + ' .slide__content *', (this.settings.transitionSpeed / 100) * 40, {
            y: -20,
            opacity: 0,
            ease: this.settings.ease + '.in',
            stagger: 0.1,
        }, 'slideAnimation')
        .fromTo(to + ' .slide__content *', (this.settings.transitionSpeed / 100) * 40, {
            y: 20,
            opacity: 0,
        }, {
            y: 0,
            opacity: 1,
            ease: 'Power3.out',
            stagger: 0.1,
        }, '>0.5')
        .fromTo(from + ' .slide__image', this.settings.transitionSpeed, {
            display: 'block',
            x: '0%',
        }, {
            x: dir === 'next' ? '-100%' : '100%',
            ease: this.settings.ease + '.inOut',
        }, 'slideAnimation')
        .fromTo(from + ' .slide__image img', this.settings.transitionSpeed, {
            transformOrigin: 'center',
            x: '0%',
        }, {
            x: dir === 'next' ? '50%' : '-50%',
            ease: this.settings.ease + '.inOut',
        }, 'slideAnimation')
        .fromTo(to + ' .slide__image img', this.settings.transitionSpeed, {
            transformOrigin: 'center',
            x: dir === 'next' ? '-50%' : '50%',
        }, {
            x: '0%',
            ease: this.settings.ease + '.inOut',
        }, 'slideAnimation')
        .fromTo(to + ' .slide__image', this.settings.transitionSpeed, {
            display: 'block',
            transformOrigin: 'right center',
            x: dir === 'next' ? '100%' : '-100%',
        }, {
            x: '0%',
            ease: this.settings.ease + '.inOut',
            onComplete: () => {
                this.settings.animating = false;
                gsap.set(from, {display: 'none'});
                this.settings.imageScale.kill();
                gsap.set(from + ' .slide__image', {scale: 1});
                this.settings.imageScale = gsap.to(to + ' .slide__image img', 15, {scale: 1.1, ease: "sine.inOut", yoyo:true, yoyoEase: true, repeat: -1});
            }
        }, 'slideAnimation');

        if(this.settings.autoPlay) {
            let el = this.settings.controls.nav[this.settings.currentSlide - 1].children[0].children[0];
            this.settings.timeline.fromTo(el, this.settings.autoPlaySpeed - this.settings.transitionSpeed, {
                x: '-100%'
            }, {
                x: 0,
                ease: 'none',
                onComplete: () => {
                    this.changeSlide('next');
                }
            }, '>');
        }



    },
  
};


oakSlider.init();
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.min.js