Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <p style="text-align: center; color: #95a5a6;"><small>Does not work in Internet Explorer or Edge.</small></p>
<div class="rotating-slider">
	<ul class="slides">
		<li>
			<div class="inner">
				<h2>Actual Rotating Slider</h2>
				<p>Built with math and dedication</p>
			</div>
		</li>
		<li>
			<div class="inner"></div>
		</li>
		<li>
			<div class="inner">
				<h2>Hates IE</h2>
				<p>Uses clip-path to shape slides</p>
			</div>
		</li>
		<li>
			<div class="inner">
			</div>
		</li>
		<li>
			<div class="inner">
				<h2>Easy to use</h2>
				<p>Just add list elements in the HTML and set a height and width in the JavaScript Settings</p>
				<p><small>Now touch & drag friendly!</small></p>
			</div>
		</li>
		<li>
			<div class="inner">
				<h2>I'm not a thief!</h2>
				<p>Stock photos from www.pexels.com</p>
			</div>
		</li>
	</ul>
</div>
              
            
!

CSS

              
                .rotating-slider{
    margin: 5em auto;
    height: 360px;
	position: relative;
    width: 480px;
}
.rotating-slider ul.direction-controls{
	list-style: none;
	margin: 0;
	padding: 0;
}
.rotating-slider ul.direction-controls li.left-arrow{
	position: absolute;
		top: 50%;
		right: 100%;
	transform: translateY(-50%);
}
.rotating-slider ul.direction-controls li.right-arrow{
	position: absolute;
		top: 50%;
		left: 100%;
	transform: translateY(-50%);
}
.rotating-slider ul.direction-controls li button{
	background: rgba(0,0,0,0.2);
	border: none;
	color: white;
	cursor: pointer;
	font-size: 1.5em;
	font-weight: bold;
	height: 1.5em;
	line-height: 1.5em;
	padding: 0;
	text-align: center;
	transition: background 0.25s;
	width: 1.5em;
}
.rotating-slider ul.direction-controls li button:hover{
	background: rgba(0,0,0,0.6);
}
.rotating-slider ul.slides{
	border-radius: 50%;
    height: 100%;
    margin: 0;
    overflow: hidden;
    padding: 0;
    position: relative;
        top: 0;
        left: 50%;
    transform: translateX(-50%) rotate(0);
    transform-origin: center center;
    width: 100%;
}
.rotating-slider ul.slides li{
	background-color: #ecf0f1;
    background-position: center;
    background-size: cover;
    display: block;
    list-style: none;
    position: absolute;
    top: 0;
    left: 50%;
    text-align: center;
    transform-origin: bottom center;
    width: 100%;
}

/* Demo Styles */
@import url(https://fonts.googleapis.com/css?family=Roboto+Slab:300,700);
body{
    background: #333;
    font-family: 'Roboto Slab', sans-serif;
    font-weight: 300;
    overflow: hidden;
}
.rotating-slider ul.slides li{
	color: #fff
}
.rotating-slider ul.slides li:nth-of-type(1){
	background: #3498db;
}
.rotating-slider ul.slides li:nth-of-type(2){
	background: url('http://static.pexels.com/wp-content/uploads/2014/05/car-oldtimer-snow-342-825x550.jpg');
}
.rotating-slider ul.slides li:nth-of-type(3){
	background: #e74c3c;
}
.rotating-slider ul.slides li:nth-of-type(4){
	background: url('http://static.pexels.com/wp-content/uploads/2014/06/analog-camera-old-olympus-om-10-1528-825x550.jpg');
}
.rotating-slider ul.slides li:nth-of-type(5){
	background: #f1c40f;
}
.rotating-slider ul.slides li:nth-of-type(6){
	background: url(http://static.pexels.com/wp-content/uploads/2014/06/bridge-city-night-645-827x550.jpg);
}
.rotating-slider ul.slides li .inner{
    box-sizing: border-box;
    padding: 2em;
    height: 100%;
    width: 100%;
}
              
            
!

JS

              
                (function($){
    $.fn.rotatingSlider = function(options){
        var rotatingSlider = {
            init: function(el){
                this.$slider = $(el);
                this.$slidesContainer = this.$slider.children('ul.slides');
                this.$slides = this.$slidesContainer.children('li');
                this.$clipPath;
                this.$directionControls;
                this.$currentSlide;
                this.$nextSlide;
                this.$previousSlide;
                
                this.settings = $.extend({
                    autoRotate: true,
                    autoRotateInterval: 6000,
                    draggable: true,
                    directionControls: true,
                    directionLeftText: '&lsaquo;',
                    directionRightText: '&rsaquo;',
                    rotationSpeed: 750,
                    slideHeight: 360,
                    slideWidth: 480,
                    /* Callback Functions */
                    beforeRotationStart: function(){},
                    afterRotationStart: function(){},
                    beforeRotationEnd: function(){},
                    afterRotationEnd: function(){}
                }, options);
                
                this.slideAngle = 360 / this.$slides.length;
                this.currentRotationAngle = 0;
                this.autoRotateIntervalId = false;
                this.rotateTimoutId = false;
                this.currentlyRotating = false;
                this.readyToDrag = false;
                this.dragStartPoint;
                this.dragStartAngle;
                this.currentlyDragging = false;
                this.markupIsValid = false;
                
                this.validateMarkup();
                if(this.markupIsValid){
                    this.renderSlider();
                    this.setCurrentSlide();
                    this.bindEvents();
                    if(this.settings.autoRotate){
                        this.startAutoRotate();
                    }
                }
            },
            bindEvents: function(){
                if(this.settings.draggable){
                    this.$slidesContainer.on('mousedown touchstart', this.handleDragStart.bind(this));
                    this.$slidesContainer.on('mousemove touchmove', this.handleDragMove.bind(this));
                    this.$slidesContainer.on('mouseup mouseleave touchend', this.handleDragEnd.bind(this));
                }
                if(this.settings.directionControls){
                    this.$slider.find('ul.direction-controls .left-arrow button').click(this.handleLeftDirectionClick.bind(this));
                    this.$slider.find('ul.direction-controls .right-arrow button').click(this.handleRightDirectionClick.bind(this));
                }
            },
            handleDragStart: function(e){
                this.readyToDrag = true;
                this.dragStartPoint = (e.type === 'mousedown') ? e.pageX : e.originalEvent.touches[0].pageX;
            },
            handleDragMove: function(e){
                if(this.readyToDrag){
                    var pageX = (e.type === 'mousemove') ? e.pageX : e.originalEvent.touches[0].pageX;
                    if(
                        this.currentlyDragging === false && 
                        this.currentlyRotating === false  &&
                        (this.dragStartPoint - pageX > 10 || this.dragStartPoint - pageX < -10)
                    ){
                        this.stopAutoRotate();
                        if(this.settings.directionControls){
                            this.$directionControls.css('pointer-events', 'none');
                        }
                        window.getSelection().removeAllRanges();
                        this.currentlyDragging = true;
                        this.dragStartAngle = this.currentRotationAngle;
                    }
                    if(this.currentlyDragging){
                        this.currentRotationAngle = this.dragStartAngle - ((this.dragStartPoint - pageX) / this.settings.slideWidth * this.slideAngle);
                        this.$slidesContainer.css('transform', 'translateX(-50%) rotate('+this.currentRotationAngle+'deg)');
                    }
                }
            },
            handleDragEnd: function(e){
                this.readyToDrag = false;
                if(this.currentlyDragging){
                    this.currentlyDragging = false;
                    this.currentRotationAngle = Math.round(this.currentRotationAngle/this.slideAngle)*this.slideAngle;
                    this.rotate();
                    if(this.settings.directionControls){
                        this.$directionControls.css('pointer-events', '');
                    }
                }
            },
            handleLeftDirectionClick: function(e){
                e.preventDefault();
                this.stopAutoRotate();
                this.rotateClockwise();
            },
            handleRightDirectionClick: function(e){
                e.preventDefault();
                this.stopAutoRotate();
                this.rotateCounterClockwise();
            },
            renderSlider: function(){
                var halfAngleRadian = this.slideAngle / 2 * Math.PI/180;
                var innerRadius = 1 / Math.tan(halfAngleRadian) * this.settings.slideWidth / 2;
                var outerRadius = Math.sqrt(Math.pow(innerRadius + this.settings.slideHeight, 2) + (Math.pow((this.settings.slideWidth / 2), 2)));
                upperArcHeight = outerRadius - (innerRadius + this.settings.slideHeight);
                lowerArcHeight = innerRadius - (innerRadius * (Math.cos(halfAngleRadian)));
                var slideFullWidth = (Math.sin(halfAngleRadian) * outerRadius) * 2;
                var slideFullHeight = upperArcHeight + this.settings.slideHeight + lowerArcHeight
                var slideSidePadding = (slideFullWidth - this.settings.slideWidth) / 2;
                var fullArcHeight = outerRadius - (outerRadius * (Math.cos(halfAngleRadian)));
                var lowerArcOffset = (slideFullWidth - (Math.sin(halfAngleRadian) * innerRadius * 2)) / 2;

                /* Set height and width of slider element */
                this.$slider.css('height', this.settings.slideHeight+'px');
                this.$slider.css('width', this.settings.slideWidth+'px');

                /* Set height and width of slides container and offset width*/
                this.$slidesContainer.css('height', outerRadius*2+'px');
                this.$slidesContainer.css('width', outerRadius*2+'px');

                /* Offset width and arc height */
                this.$slidesContainer.css('transform', 'translateX(-50%)');
                this.$slidesContainer.css('top', '-'+ upperArcHeight +'px');

                /* Generate path for slide clipping */
                var pathCoords = 'M 0 '+fullArcHeight;
                pathCoords += ' A '+outerRadius+' '+outerRadius+' 0 0 1 '+slideFullWidth+' '+fullArcHeight;
                pathCoords += ' L '+(slideFullWidth-lowerArcOffset)+' '+slideFullHeight;
                pathCoords += ' A '+innerRadius+' '+innerRadius+' 0 0 0 '+lowerArcOffset+' '+slideFullHeight+' Z';
                this.$slider.append('<svg><defs><clipPath id="slideClipPath"><path /></clipPath></defs></svg>');
                this.$slider.find('#slideClipPath>path').attr('d', pathCoords);

                /* Apply styles to each slide */
                this.$slides.each(function(i, el){
                var $slide = $(el);
                    /* Set distance from point of rotation */
                    $slide.css('transform-origin', 'center '+(innerRadius + this.settings.slideHeight)+'px');

                    /* Set slide Height and Width */
                    $slide.css('height', this.settings.slideHeight+'px');
                    $slide.css('width', this.settings.slideWidth+'px');

                    /* Set calculated padding for width, upper arc height, and lower arc height */
                    $slide.css('padding', upperArcHeight +'px '+slideSidePadding+'px '+lowerArcHeight+'px '+slideSidePadding+'px ');

                    /* Offset container Arc Height */
                    $slide.css('top', upperArcHeight +'px');

                    /* Offset Width, then Rotate Slide, then offset individual Top Arcs  */
                    $slide.css('transform', 'translateX(-50%) rotate('+this.slideAngle * i+'deg) translateY(-'+ upperArcHeight +'px)');

                    /* Add clipping path  */
                    $slide.css('-webkit-clip-path', 'url(#slideClipPath)');
                    $slide.css('clip-path', 'url(#slideClipPath)');
                }.bind(this));
                
                /* Render Arrow Controls */
                if(this.settings.directionControls){
                    var directionArrowsHTML = '<ul class="direction-controls">';
                    directionArrowsHTML += '<li class="left-arrow"><button>'+this.settings.directionLeftText+'</button></li>';
                    directionArrowsHTML += '<li class="right-arrow"><button>'+this.settings.directionRightText+'</button></li>';
                    directionArrowsHTML += '</ul>';
                    this.$slider.append(directionArrowsHTML);
                    this.$directionControls = this.$slider.find('ul.direction-controls');
                }
                
            },
            rotateClockwise: function(){
                this.currentRotationAngle = this.currentRotationAngle + this.slideAngle;
                this.rotate();
            },
            rotateCounterClockwise: function(){
                this.currentRotationAngle = this.currentRotationAngle - this.slideAngle;
                this.rotate();
            },
            rotate: function(){
                this.beforeRotationStart();
                this.currentlyRotating = true;
                this.$slider.addClass('currently-rotating');
                this.setCurrentSlide();

                if(this.rotateTimeoutId){
                    clearTimeout(this.rotateTimeoutId);
                    this.rotateTimeoutId = false;
                }
                
                this.$slidesContainer.css('transition', 'transform '+(this.settings.rotationSpeed/1000)+'s ease-in-out');
                this.$slidesContainer.css('transform', 'translateX(-50%) rotate('+this.currentRotationAngle+'deg)');

                this.afterRotationStart();
                
                this.rotateTimeoutId = setTimeout(function(){
                    this.beforeRotationEnd();
                    this.currentlyRotating = false;
                    this.$slider.removeClass('currently-rotating');
                    this.$slidesContainer.css('transition', 'none');

                    /* keep currentRotationAngle between -360 and 360 */
                    if(this.currentRotationAngle >= 360 || this.currentRotationAngle <= -360){
                        this.currentRotationAngle = this.currentRotationAngle >= 360 ? this.currentRotationAngle - 360 : this.currentRotationAngle + 360;
                        this.$slidesContainer.css('transform', 'translateX(-50%) rotate('+this.currentRotationAngle+'deg)');
                    }
                    this.afterRotationEnd();
                }.bind(this), this.settings.rotationSpeed);
            },
            setCurrentSlide: function(){
                var currAngle = this.currentRotationAngle;
                if(this.currentRotationAngle >= 360 || this.currentRotationAngle <= -360){
                     currAngle = currAngle >= 360 ? currAngle - 360 : currAngle + 360;
                }
                this.$currentSlide = this.$slides.eq(-currAngle / this.slideAngle);
                this.$nextSlide = (this.$currentSlide.is(':last-child') ? this.$slides.first() : this.$currentSlide.next());
                this.$previousSlide = (this.$currentSlide.is(':first-child') ? this.$slides.last() : this.$currentSlide.prev());

                this.$slides.removeClass('active-slide');
                this.$slides.removeClass('next-slide');
                this.$slides.removeClass('previous-slide');

                this.$currentSlide.addClass('active-slide');
                this.$nextSlide.addClass('next-slide');
                this.$previousSlide.addClass('previous-slide');
            },
            startAutoRotate: function(){
                this.autoRotateIntervalId = setInterval(function(){
                    this.rotateCounterClockwise();
                }.bind(this), this.settings.autoRotateInterval);
            },
            stopAutoRotate: function(){
                if(this.autoRotateIntervalId){
                    clearInterval(this.autoRotateIntervalId);
                    this.autoRotateIntervalId = false;
                }
            },
            validateMarkup: function(){
                if(
                    this.$slider.hasClass('rotating-slider') &&
                    this.$slidesContainer.length === 1 &&
                    this.$slides.length >= 2
                ){
                    this.markupIsValid = true;
                }else{
                    this.$slider.css('display', 'none');
                    console.log('Markup for Rotating Slider is invalid.');
                }
            },

            /* Callbacks */
            beforeRotationStart: function(){
                this.settings.beforeRotationStart();
            },
            afterRotationStart: function(){
                this.settings.afterRotationStart();
            },
            beforeRotationEnd: function(){
                this.settings.beforeRotationEnd();
            },
            afterRotationEnd: function(){
                this.settings.afterRotationEnd();
            },
        };

        return this.each(function(){
            rotatingSlider.init(this);
        });
    };
}(jQuery));

$(function(){ 
    $('.rotating-slider').rotatingSlider({
		slideHeight : Math.min(360, window.innerWidth -80),
		slideWidth : Math.min(480, window.innerWidth - 80),
	});
}); 
              
            
!
999px

Console