$(function(){ var $slider = $('.slider') , slider_width = 0 , $slider_inner = $slider.children().first() , $elements = $slider_inner.children('.element') , elements_count = $elements.length , element_width = $elements.first().width() , element_margin = 0 , elements_fit = 0 , visible_width = 0 function onResize() { slider_width = $slider.width() elements_fit = Math.floor(slider_width/element_width) // we have a limited number of elements if (elements_fit > elements_count) { elements_fit = elements_count } // we need only odd number if (elements_fit % 2 === 0) { elements_fit -= 1 } // find element margin for balancing element_margin = Math.ceil((slider_width - (element_width * elements_fit))/(elements_fit * 2)) // set container width * 1.5 to fit clonned elements when scroll visible_width = (element_width + element_margin * 2) * elements_fit $slider_inner.width(Math.ceil(visible_width * 1.5)) // add margins $elements.css({'margin-left': element_margin + 'px', 'margin-right': element_margin + 'px'}) // set active element $elements.removeClass('active') $elements.slice(Math.floor(elements_fit/2), Math.floor(elements_fit/2) + 1).addClass('active') } function goTo(index_to) { var index_past = Math.floor(elements_fit/2) // if active element if (index_to === index_past) { return } var index_diff = index_to - index_past , $elements_slice , left_to = 0 if (index_diff > 0) { $elements_slice = $elements.slice(0, index_diff) // append diff elements $elements_slice.clone().appendTo($slider_inner) // compute left offset left_to = -((element_width + element_margin * 2) * index_diff) } else { $elements_slice = $elements.slice(index_diff) // append diff elements $elements_slice.clone().prependTo($slider_inner) // set left offset $slider_inner.css('left', (element_width + element_margin * 2) * index_diff + 'px') } // reindex elements $elements = $slider_inner.children('.element') // scroll to position $slider_inner.animate({ left: left_to + 'px' }, { duration: 1000 , easing: 'swing' , complete: function() { // remove duplicates $elements_slice.remove() // reposition slider $slider_inner.css('left', 0) // reindex elements $elements = $slider_inner.children('.element') // set active element $elements.removeClass('active') $elements.slice(Math.floor(elements_fit/2), Math.floor(elements_fit/2) + 1).addClass('active') } }) } onResize() $(window).on('resize', onResize) $slider .on('click', 'a.slider-control', function(ev){ ev.preventDefault() var direction = $(this).hasClass('left') ? -1 : 1 goTo(Math.floor(elements_fit/2) + direction) }) .on('click', '.element', function(ev){ ev.preventDefault() goTo($elements.index(this)) }) })
.slider{ position: relative; overflow: hidden; height: 230px; background-image: linear-gradient(to bottom, #d1dfea, #adc6da); } .slider-inner{ height: 230px; position: absolute; top: 0; left: 0; } /* Element properties */ .element{ width: 200px; height: 230px; float: left; text-align: center; } .element .image{ height: 102px; } .element .image .active{ display: none; } .element .title{ padding: 3px 20px 0; font-size: 14px; opacity: 0.5; transition: 0.2s linear opacity; text-transform: uppercase; } .element .title a{ color: #336791; } /* Active element properties */ .element.active .image .default{ display: none; } .element.active .image .active{ display: inline-block; } .element.active .title{ opacity: 1; } /* Slider controls */ .slider-control{ position: absolute; top: 60px; display: block; width: 0; height: 0; margin: 0 101px; border-color: transparent; border-style: solid; opacity: 0.7; } .slider-control:hover{ opacity: 1; } .slider-control.left{ right: 50%; border-width: 16px 19px 16px 0; border-right-color: #336791; } .slider-control.right{ left: 50%; border-width: 16px 0 16px 19px; border-left-color: #336791; }