3D Responsive Split Carousel With jQuery And CSS3

File Size: 3.46 KB
Views Total: 9953
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   
3D Responsive Split Carousel With jQuery And CSS3

This is a pretty cool Split 3D Carousel written in jQuery and CSS3 which enables you to slide through 2 associated cubes in different directions with side navigation and keyboard interactions.

How to use it:

1. The primary HTML structure for the split 3D carousel.

<div class="carousel">
  <div class="carousel__control"> </div>
  <div class="carousel__stage">
    <div class="spinner spinner--left">
      <div class="spinner__face js-active" data-bg="#27323c">
        <div class="content" data-type="carousel-1">
          <div class="content__left">
            <h1>Title 1<br>
              <span>Subtitle 1</span></h1>
          </div>
          <div class="content__right">
            <div class="content__main">
              <p>Description 1</p>
            </div>
            <h3 class="content__index">01</h3>
          </div>
        </div>
      </div>
      <div class="spinner__face" data-bg="#19304a">
        <div class="content" data-type="carousel-2">
          <div class="content__left">
            <h1>Title 2<br>
              <span>Subtitle 2</span></h1>
          </div>
          <div class="content__right">
            <div class="content__main">
              <p>Description 2</p>
            </div>
            <h3 class="content__index">02</h3>
          </div>
        </div>
      </div>
      <div class="spinner__face" data-bg="#2b2533">
        <div class="content" data-type="carousel-3">
          <div class="content__left">
            <h1>Title 3<br>
              <span>Subtitle 3</span></h1>
          </div>
          <div class="content__right">
            <div class="content__main">
              <p>Description 3</p>
            </div>
            <h3 class="content__index">03</h3>
          </div>
        </div>
      </div>
      <div class="spinner__face" data-bg="#312f2d">
        <div class="content" data-type="carousel-4">
          <div class="content__left">
            <h1>Title 4<br>
              <span>Subtitle 4</span></h1>
          </div>
          <div class="content__right">
            <div class="content__main">
              <p>Description 4</p>
            </div>
            <h3 class="content__index">04</h3>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

2. The primary CSS/CSS3 styles:

.carousel {
  position: relative;
  height: 100%;
  overflow: hidden;
  -webkit-perspective: 50vw;
  perspective: 50vw;
  -webkit-perspective-origin: 50% 50%;
  perspective-origin: 50% 50%;
}

.carousel__stage {
  position: absolute;
  top: 20px;
  bottom: 20px;
  left: 20px;
  right: 20px;
  margin: auto;
  -webkit-transform-style: preserve-3d;
  transform-style: preserve-3d;
  -webkit-transform: translateZ(calc(-50vh + 20px));
  transform: translateZ(calc(-50vh + 20px));
}

.spinner {
  position: absolute;
 width: calc(50vw - (20px));
  height: calc(100vh - 40px);
  top: 0;
  left: 0;
  right: auto;
  bottom: 0;
  margin: auto;
  -webkit-transform-style: preserve-3d;
  transform-style: preserve-3d;
  -webkit-transition: -webkit-transform 1s;
  transition: -webkit-transform 1s;
  transition: transform 1s;
  transition: transform 1s, -webkit-transform 1s;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  -webkit-transform-origin: 50% 50%;
  transform-origin: 50% 50%;
  -webkit-transform: rotateX(0);
  transform: rotateX(0);
}

.js-spin-fwd .spinner {
  -webkit-transform: rotateX(-90deg);
  transform: rotateX(-90deg);
}

.js-spin-bwd .spinner {
  -webkit-transform: rotateX(90deg);
  transform: rotateX(90deg);
}

.js-spin-fwd .spinner--right {
  -webkit-transform: rotateX(90deg);
  transform: rotateX(90deg);
}

.js-spin-bwd .spinner--right {
  -webkit-transform: rotateX(-90deg);
  transform: rotateX(-90deg);
}

.spinner--right {
  right: 0;
  left: auto;
}

.spinner__face {
  display: none;
  position: absolute;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.spinner__face.js-next {
  display: block;
  -webkit-transform: rotateX(90deg) translateZ(calc(50vh - 20px));
  transform: rotateX(90deg) translateZ(calc(50vh - 20px));
}

.spinner--right .spinner__face.js-next {
  -webkit-transform: rotateX(270deg) translateZ(calc(50vh - 20px));
  transform: rotateX(270deg) translateZ(calc(50vh - 20px));
}

.js-spin-bwd .spinner__face.js-next {
  -webkit-transform: rotateX(-90deg) translateZ(calc(50vh - 20px));
  transform: rotateX(-90deg) translateZ(calc(50vh - 20px));
}

.js-spin-bwd .spinner--right .spinner__face.js-next {
  -webkit-transform: rotateX(-270deg) translateZ(calc(50vh - 20px));
  transform: rotateX(-270deg) translateZ(calc(50vh - 20px));
}

.js-active {
  display: block;
  -webkit-transform: translateZ(calc(50vh - 20px));
  transform: translateZ(calc(50vh - 20px));
}

.content {
  position: absolute;
  width: 200%;
  height: 100%;
  left: 0;
}

.spinner--right .content { left: -100%; }

.content__left, .content__right {
  position: absolute;
  left: 0;
  top: 0;
  width: 50%;
  height: 100%;
}

.content__right {
  right: 0;
  left: auto;
}

.content__left {
  background-repeat: no-repeat;
  background-size: cover;
}

.content__left:after {
  position: absolute;
  display: block;
  content: "";
  width: 100%;
  height: 100%;
  background-color: rgba(0,0,0,0.1);
}

.content__left h1 {
  position: absolute;
  top: 50%;
  margin-top: -3vw;
  text-align: center;
  font-family: oswald;
  font-size: 5vw;
  height: 10vw;
  opacity: 1;
  color: #fff;
  width: 100%;
  letter-spacing: 0.15em;
  line-height: 0.6;
}

.content__left span {
  font-size: 1vw;
  font-weight: 300;
  letter-spacing: 0.2em;
  opacity: 0.9;
  font-family: Merriweather;
}

.content__right {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
}

.content__right .content__main {
  position: absolute;
  font-family: Merriweather, serif;
  text-align: left;
  color: #fff;
  font-size: 1.3vw;
  padding: 0 8vw;
  line-height: 1.65;
  font-weight: 300;
  margin: 0;
  opacity: 0.8;
}

.content__right .content__main p:last-child {
  text-transform: uppercase;
  letter-spacing: 0.15em;
  font-size: 0.85em;
}

.content__right .content__index {
  font-size: 30vh;
  position: absolute;
  right: -1vh;
  top: 35vh;
  opacity: 0.04;
  font-family: oswald;
  color: #fff;
}

3. Add background images to the carousel.

[data-type="carousel-1"] .content__left { background-image: url("1.jpg"); }

.spinner--right [data-type="carousel-1"] .content__left { background-image: none; }

[data-type="carousel-2"] .content__left { background-image: url("2.jpg"); }

.spinner--right [data-type="carousel-2"] .content__left { background-image: none; }

[data-type="carousel-3"] .content__left { background-image: url("3.jpg"); }

.spinner--right [data-type="carousel-3"] .content__left { background-image: none; }

[data-type="carousel-4"] .content__left { background-image: url("4.jpg"); }

.spinner--right [data-type="carousel-4"] .content__left { background-image: none; }

4. The Split 3D Carousel requires the latest version of jQuery library loaded at the end of the document.

<script src="//code.jquery.com/jquery-3.1.1.min.js"></script> 

5. The main jQuery script to active the Split 3D Carousel. Add the following JS snippets after your jQuery library and done.

var activeIndex = 0;
var limit = 0;
var disabled = false;
var $stage = undefined;
var $controls = undefined;
var canvas = false;
var SPIN_FORWARD_CLASS = 'js-spin-fwd';
var SPIN_BACKWARD_CLASS = 'js-spin-bwd';
var DISABLE_TRANSITIONS_CLASS = 'js-transitions-disabled';
var SPIN_DUR = 1000;
var appendControls = function appendControls() {
    for (var i = 0; i < limit; i++) {
        $('.carousel__control').append('<a href="#" data-index="' + i + '"></a>');
    }
    var height = $('.carousel__control').children().last().outerHeight();
    $('.carousel__control').css('height', 30 + limit * height);
    $controls = $('.carousel__control').children();
    $controls.eq(activeIndex).addClass('active');
};
var setIndexes = function setIndexes() {
    $('.spinner').children().each(function (i, el) {
        $(el).attr('data-index', i);
        limit++;
    });
};
var duplicateSpinner = function duplicateSpinner() {
    var $el = $('.spinner').parent();
    var html = $('.spinner').parent().html();
    $el.append(html);
    $('.spinner').last().addClass('spinner--right');
    $('.spinner--right').removeClass('spinner--left');
};
var paintFaces = function paintFaces() {
    $('.spinner__face').each(function (i, el) {
        var $el = $(el);
        var color = $(el).attr('data-bg');
        $el.children().css('backgroundImage', 'url(' + getBase64PixelByColor(color) + ')');
    });
};
var getBase64PixelByColor = function getBase64PixelByColor(hex) {
    if (!canvas) {
        canvas = document.createElement('canvas');
        canvas.height = 1;
        canvas.width = 1;
    }
    if (canvas.getContext) {
        var ctx = canvas.getContext('2d');
        ctx.fillStyle = hex;
        ctx.fillRect(0, 0, 1, 1);
        return canvas.toDataURL();
    }
    return false;
};
var prepareDom = function prepareDom() {
    setIndexes();
    paintFaces();
    duplicateSpinner();
    appendControls();
};
var spin = function spin() {
    var inc = arguments.length <= 0 || arguments[0] === undefined ? 1 : arguments[0];
    if (disabled)
        return;
    if (!inc)
        return;
    activeIndex += inc;
    disabled = true;
    if (activeIndex >= limit) {
        activeIndex = 0;
    }
    if (activeIndex < 0) {
        activeIndex = limit - 1;
    }
    var $activeEls = $('.spinner__face.js-active');
    var $nextEls = $('.spinner__face[data-index=' + activeIndex + ']');
    $nextEls.addClass('js-next');
    if (inc > 0) {
        $stage.addClass(SPIN_FORWARD_CLASS);
    } else {
        $stage.addClass(SPIN_BACKWARD_CLASS);
    }
    $controls.removeClass('active');
    $controls.eq(activeIndex).addClass('active');
    setTimeout(function () {
        spinCallback(inc);
    }, SPIN_DUR, inc);
};
var spinCallback = function spinCallback(inc) {
    $('.js-active').removeClass('js-active');
    $('.js-next').removeClass('js-next').addClass('js-active');
    $stage.addClass(DISABLE_TRANSITIONS_CLASS).removeClass(SPIN_FORWARD_CLASS).removeClass(SPIN_BACKWARD_CLASS);
    $('.js-active').each(function (i, el) {
        var $el = $(el);
        $el.prependTo($el.parent());
    });
    setTimeout(function () {
        $stage.removeClass(DISABLE_TRANSITIONS_CLASS);
        disabled = false;
    }, 100);
};
var attachListeners = function attachListeners() {
    document.onkeyup = function (e) {
        switch (e.keyCode) {
        case 38:
            spin(-1);
            break;
        case 40:
            spin(1);
            break;
        }
    };
    $controls.on('click', function (e) {
        e.preventDefault();
        if (disabled)
            return;
        var $el = $(e.target);
        var toIndex = parseInt($el.attr('data-index'), 10);
        spin(toIndex - activeIndex);
    });
};
var assignEls = function assignEls() {
    $stage = $('.carousel__stage');
};
var init = function init() {
    assignEls();
    prepareDom();
    attachListeners();
};
$(function () {
    init();
});

This awesome jQuery plugin is developed by paulnoble. For more Advanced Usages, please check the demo page or visit the official website.