cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - Activehtmlicon-personicon-teamoctocatpop-outspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External CSS

These stylesheets will be added in this order and before the code you write in the CSS editor. You can also add another Pen here, and it will pull the CSS from it. Try typing "font" or "ribbon" below.

Quick-add: + add another resource

Add External JavaScript

These scripts will run in this order and before the code in the JavaScript editor. You can also link to another Pen here, and it will run the JavaScript from it. Also try typing the name of any popular library.

Quick-add: + add another resource

Code Indentation

     

Save Automatically?

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.

            
              <nav class="navbar navbar-inverse">
  <div class="container-fluid">
    <div class="navbar-header">
      <a class="navbar-brand" href="#">
        otto.slider
      </a>
    </div>
  </div>
</nav>
<div id="otto-slider-container"></div>
<div class="container">
  <div class="row">
    <div class="col-md-6">
      <h2>otto.slider</h2>
      <p>jQuery responsive slideshow with endless animation.</p>
      <p>This example uses bootstrap and FA, not mandatory.</p>
      <p>Options:</p>
      <ul>
        <li>autostart</li>
        <li>auto interval</li>
        <li>read_all_text</li>
      </ul>
    </div>
    <div class="col-md-6">
      <h2>Usage</h2>
      <p>Check the js code after "USAGE".</p>
      <p>Create items setting image, title, text, url.</p>
      <p>
        <a href="http://www.abidibo.net" target="_blank">
          <img alt="abidibo" src="http://www.abidibo.net/static/abidibo_net/img/abidibo_30px.png">
        </a>
        <a href="http://www.otto.to.it" target="_blank">
          <img src="https://avatars2.githubusercontent.com/u/1119279?v=3&s=200" style="height: 40px" />
        </a>
      </p>
    </div>
  </div>
</div>
            
          
!
            
              /** main */
body {
  background: #000;
}
.container {
  background: #222;
  color: #fff;
}
h2 {
  color: #ff6600;
}
/** navbar */
.navbar {
    border-radius: 0;
    margin-bottom: 0;
}

/** otto.slider */
.os-rail {
    position: relative;
}
.os-arrow {
    position: absolute;
    top: 50%;
    margin-top: -20px;
    font-size: 60px;
    color: #000;
    text-shadow: 0px 0px 1px #fff;
}
.os-arrow:hover {
    text-decoration: none;
    cursor: pointer;
    display: inline-block;
}
.os-slide {
    display: inline-block;
    position: relative;
    margin: 0;
    padding: 0;
}
.os-slide .caption {
    position: absolute;
    display: none;
    top: 20px;
    left: 20px;
    width: 400px;
    max-width: 80%;
}
.os-slide.os-active .caption {
    display: block;
}
.os-slide h1 span {
    background: #fff;
    display: inline-block;
    padding: 0 5px;
    font-size: 36px;
    line-height: 46px;
}
.os-slide .text {
    padding: 5px;
    background: rgba(255, 255, 255, 0.8);
}
.os-slide img {
    opacity: 0.5;
    transition: 0.8s opacity ease;
}
.os-slide.os-active img {
    opacity: 1;
}
.os-slide .readall {
    display: none;
    position: absolute;
    bottom: 0px;
    right: 0px;
    width: 228px;
    height: 30px;
    text-align: center;
    background: rgba(0, 0, 0, 0.5);
}
.os-slide .readall a {
    font-size: 20px;
    color: #fff;
    line-height: 30px;
}
.os-slide .readall a:after {
    content: 
}
.os-slide.os-active .readall {
    display: block;
}
            
          
!
            
              /**
 * otto.slider
 * Horizontal slider banner with circular animation
 * @author abidibo <abidibo@gmail.com>
 * @copyright 2015 Otto srl
 * @license MIT
 */
(function($) {
    window.OttoSlider = function(container, items, opts) {
        var options = {
            autostart: true,
            autointerval: 5000,
            read_all_text: 'read all'
        };

        /**
         * Inits the component
         */
        this.init = function() {
            this.container = $(container);
            // create items for circular structure, the first item is appended at the end of the stack
            var last = items.pop();
            this.items = $.merge([last], $.merge(items, [last, items[0]]));
            this.cnt_loaded = 0;

            this.slides = [];
            this.active_index = 1;

            this.options = $.extend({}, options, opts);

            this.width = this.container.width();
            console.info('os: container width: ', this.width);

            // set some style on the container
            this.container.css('overflow', 'hidden');
            this.container.css('position', 'relative');

            // render the component
            this.render();
            // when resizing update the component
            var self = this;
            $(window).on('resize', function() {
                console.info('os: resizing window');
                self.size();
            })
            // set the active slider
            this.setActiveSlider(1);

            this.interval = null;
            if(this.options.autostart) {
                var self = this;
                self.interval = setInterval(function() {
                    self.gonext('auto');
                }, this.options.autointerval);
            }

        };

        this.loaded = function() {
            console.log('loaded');
            this.cnt_loaded++;
            if(this.cnt_loaded == this.items.length) {
                this.size();
            }
        }

        /**
         * Renders the component
         */
        this.render = function() {
            var self = this;
            // the rail keeps all the slides
            this.rail = $('<div/>', { 'class': 'os-rail' }).appendTo(this.container);
            this.rail.css('transition-duration', '0s');
            for (var i = 0, len = this.items.length; i < len; i++) {
                var item = this.items[i];
                var slide = $('<section/>', { 'class': 'os-slide' }).appendTo(this.rail);
                this.slides.push(slide);
                slide.img = $('<img/>', {
                    src: item.img_url
                }).appendTo(slide);
                slide.img.on('load', function() { self.loaded() });
                var caption = $('<div/>', { 'class': 'caption' }).appendTo(slide);
                slide.title = $('<h1/>').html(item.title).appendTo(caption);
                slide.text = $('<div/>', { 'class': 'text' }).html(item.text).appendTo(caption);
                slide.readall = $('<div/>', { 'class': 'readall' }).html('<a href="' + item.url + '">' + this.options.read_all_text + '</a>').appendTo(slide);
            }
            // navigation buttons
            this.prev = $('<a/>', { 'class': 'fa fa-chevron-left os-arrow os-prev' }).appendTo(this.container).click($.proxy(this.goprev, this));
            this.next = $('<a/>', { 'class': 'fa fa-chevron-right os-arrow os-next' }).appendTo(this.container).click($.proxy(this.gonext, this));

            var self = this;
            setTimeout(function() {
                self.rail.css('transition-duration', '0.5s');
            })
        };

        /**
         * Sets all the component dimensions
         * Called at the beginning and when resizing the window
         */
        this.size = function() {
            // update container width
            this.width = this.container.width();
            // update img max-width
            this.container.find('img').css('max-width', (this.width - 80) + 'px');
            // update rail width (maybe img width has changed)
            var width = 0;
            for (var i = 0, len = this.slides.length; i < len; i++) {
                width += this.slides[i].img.width();
            }
            this.rail.width = width;
            this.rail.css('width', (width * 2) + 'px');
            // slide width
            this.slide_width = width / this.items.length;
            // I use margin left as animation property
            // I store the calculated margin left value in order to have right calculation when the nav button
            // is pressed before the animation ends (in such case a live calculation of the margin will create problems)
            this.rail.margin_left = this.calculateMargin();
            this.rail.init_margin_left = this.calculateMargin();
            this.rail.css('margin-left', this.rail.margin_left + 'px');
            // reposition navigation buttons
            this.prev.css('right', (this.width + this.slide_width + 10) / 2 + 'px');
            this.next.css('left', (this.width + this.slide_width +10) / 2 + 'px');
        };

        /**
         * Calculates the rail left margin in order to show the active_index slide
         */
        this.calculateMargin = function() {
            var margin = (-(3 * this.slide_width - this.width) / 2) + (1 - this.active_index) * this.slide_width;
            return margin;
        };

        /**
         * Sets the active slide
         * @param {Number} index
         */
        this.setActiveSlider = function(index) {
            $('.os-slide').removeClass('os-active');
            this.active_index = index < 0 ? this.items.length - 1 : index % this.items.length;
            this.rail.css('margin-left', this.calculateMargin() + 'px');
            this.slides[this.active_index].addClass('os-active');
        };

        /**
         * Show prev slide
         */
        this.goprev = function(clearinterval) {
            if(arguments[0] !== 'auto') {
                clearInterval(this.interval);
            }
            this.setActiveSlider(this.active_index - 1);
            // if the shown slide is the first one, then traslate all as we're seeing the penultimate slide
            // without animation
            if(this.active_index == 0) {
                var self = this;
                setTimeout(function() {
                    self.rail.css('transition-duration', '0s'); // no animation!
                    self.setActiveSlider(self.items.length - 2);
                    setTimeout(function() {self.rail.css('transition-duration', '0.5s');}, 100);
                }, 500);
            }
        };

        /**
         * Show next slide
         */
        this.gonext = function() {
            if(arguments[0] !== 'auto') {
                clearInterval(this.interval);
            }
            this.setActiveSlider(this.active_index + 1);
            // if the shown slide is the last one, then reset to the initial state
            // without animation
            if(this.active_index == this.items.length - 1) {
                var self = this;
                setTimeout(function() { 
                    self.rail.css('transition-duration', '0s'); // no animation!
                    self.setActiveSlider(1);
                    setTimeout(function() {self.rail.css('transition-duration', '0.5s');}, 100);
                }, 500);
            }
        };

        this.init();

    }
})(jQuery)

/** end otto.slider */

/**
 * USAGE
 */
var items = [];
items.push({
    'img_url': 'http://lorempixel.com/1000/298/nature',
    'title': '<span>My</span> <span>title</span> <span>1</span>',
    'text': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse dapibus hendrerit purus, in pellentesque enim viverra accumsan. Donec id tincidunt mi. Aenean ultrices vulputate niosl, at convallis ipsum auctor sit amet. Vestibulum ac vestibulum massa, nec venenatis urna',
    'url': 'http://www.abidibo.net/blog/2015/01/27/responsive-menu-bootstrap/'
});
items.push({
    'img_url': 'http://lorempixel.com/1000/300/nature',
    'title': '<span>My</span> <span>title</span> <span>2</span>',
    'text': 'Donec volutpat mauris quis leo tempor vulputate. Proin in efficitur lacus. Praesent ex libero, posuere eu libero eu, consectetur ornare leo. In venenatis posuere lectus. Mauris eu ligula nec enim pellentesque eleifend eleifend eu dolor. Vestibulum mattis lectus non erat lacinia aliquam. Etiam egestas nunc ut mi fringilla eleifend',
    'url': 'http://www.abidibo.net/blog/2012/01/26/the-importance-of-semantics-in-html-documents/'
});
items.push({
    'img_url': 'http://lorempixel.com/1000/301/nature',
    'title': '<span>My</span> <span>title</span> <span>3</span>',
    'text': 'In iaculis tempus eros vitae iaculis. Suspendisse laoreet quis orci at fermentum. Nam condimentum, lorem gravida interdum varius, mi dolor egestas quam',
    'url': 'http://www.abidibo.net/blog/2013/09/20/ajsut-abidibos-javascript-unit-testing-library/'
});
items.push({
    'img_url': 'http://lorempixel.com/1000/299/nature',
    'title': '<span>My</span> <span>title</span> <span>4</span>',
    'text': 'In iaculis tempus eros vitae iaculis. Suspendisse laoreet quis orci at fermentum. Nam condimentum, lorem gravida interdum varius, mi dolor egestas quam',
    'url': 'http://www.abidibo.net'
});
var slider = new OttoSlider('#otto-slider-container', items, { autostart: true, read_all_text: 'read all »' });


            
          
!
999px
Close

Asset uploading is a PRO feature.

As a PRO member, you can drag-and-drop upload files here to use as resources. Images, Libraries, JSON data... anything you want. You can even edit them anytime, like any other code on CodePen.

Go PRO

Loading ..................

Console