Responsive Diagonal 'Step' Slider
Following on from this tutorial this is the slider from a recent real world project
A Pen by Nick Moreton on CodePen.
<h2>Responsive Diagonal 'Step' Slider</h2> | |
<div class="slider"> | |
<div class="slider__title"> | |
<h4>Featured Articles</h4> | |
</div> | |
<div class="controls"> | |
<button class="previous"> | |
<svg version="1.1" id="Isolation_Mode" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" | |
y="0px" viewBox="0 0 67.9 105.6" style="enable-background:new 0 0 67.9 105.6;" xml:space="preserve"> | |
<rect x="4.4" y="4.4" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -6.2476 15.0829)" width="21.3" height="21.3"/> | |
<rect x="23.3" y="23.3" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -14.0571 33.9364)" width="21.3" height="21.3"/> | |
<rect x="42.1" y="42.1" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -21.8666 52.7902)" width="21.3" height="21.3"/> | |
<rect x="23.3" y="61" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -40.7202 44.9807)" width="21.3" height="21.3"/> | |
<rect x="4.4" y="79.8" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -59.5738 37.1712)" width="21.3" height="21.3"/> | |
</svg> | |
</button> | |
<button class="next"> | |
<svg version="1.1" id="Isolation_Mode" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" | |
y="0px" viewBox="0 0 67.9 105.6" style="enable-background:new 0 0 67.9 105.6;" xml:space="preserve"> | |
<rect x="4.4" y="4.4" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -6.2476 15.0829)" width="21.3" height="21.3"/> | |
<rect x="23.3" y="23.3" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -14.0571 33.9364)" width="21.3" height="21.3"/> | |
<rect x="42.1" y="42.1" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -21.8666 52.7902)" width="21.3" height="21.3"/> | |
<rect x="23.3" y="61" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -40.7202 44.9807)" width="21.3" height="21.3"/> | |
<rect x="4.4" y="79.8" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -59.5738 37.1712)" width="21.3" height="21.3"/> | |
</svg> | |
<button> | |
</div> | |
<div class="slider__inner"> | |
<div class="slider__slide"> | |
<a class="slider__slide__image" href="#" style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/110131/3.jpeg)"></a> | |
<div class="slider__slide__content" data-background="#c84977" style="background-color:#c84977;"> | |
<div class="slider__slide__content__categories"><a href="#">Blog</a>, <a href="#">Music</a>, <a href="#">Travel</a> </div> | |
<h3>Slide Title One</h3> | |
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Vel repudiandae quo dolorem ipsum deleniti voluptates voluptatibus natus obcaecati dolore porro.</p> | |
<a href="#" class="read-more">Read More <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/110131/chev.png"></a> | |
</div> | |
</div> | |
<div class="slider__slide"> | |
<a class="slider__slide__image" href="#" style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/110131/4.jpeg)"></a> | |
<div class="slider__slide__content" data-background="#db5944" style="background-color:#db5944;"> | |
<div class="slider__slide__content__categories"><a href="#">Articles</a>, <a href="#">Music</a>, <a href="#">Film</a> </div> | |
<h3>Slide Title Two</h3> | |
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Vel repudiandae quo dolorem ipsum deleniti voluptates voluptatibus natus obcaecati dolore porro.</p> | |
<a href="#" class="read-more">Read More <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/110131/chev.png"></a> | |
</div> | |
</div> | |
<div class="slider__slide"> | |
<a class="slider__slide__image" href="#" style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/110131/5.jpeg)"></a> | |
<div class="slider__slide__content" data-background="#e2c142" style="background-color:#e2c142;"> | |
<div class="slider__slide__content__categories"><a href="#">Blog</a>, <a href="#">Music</a>, <a href="#">Travel</a> </div> | |
<h3>Slide Title Three</h3> | |
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Vel repudiandae quo dolorem ipsum deleniti voluptates voluptatibus natus obcaecati dolore porro.</p> | |
<a href="#" class="read-more">Read More <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/110131/chev.png"></a> | |
</div> | |
</div> | |
<div class="slider__slide"> | |
<a class="slider__slide__image" href="#" style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/110131/1.jpeg)"></a> | |
<div class="slider__slide__content" data-background="#43cab1" style="background-color:#43cab1;"> | |
<div class="slider__slide__content__categories"><a href="#">News</a>, <a href="#">Sport</a></div> | |
<h3>Slide Title Four</h3> | |
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Vel repudiandae quo dolorem ipsum deleniti voluptates voluptatibus natus obcaecati dolore porro.</p> | |
<a href="#" class="read-more">Read More <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/110131/chev.png"></a> | |
</div> | |
</div> | |
<div class="slider__slide"> | |
<a class="slider__slide__image" href="#" style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/110131/2.jpeg)"></a> | |
<div class="slider__slide__content" data-background="#466cba" style="background-color:#466cba;"> | |
<div class="slider__slide__content__categories"><a href="#">Blog</a>, <a href="#">Music</a>, <a href="#">Travel</a> </div> | |
<h3>Slide Title Five</h3> | |
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Vel repudiandae quo dolorem ipsum deleniti voluptates voluptatibus natus obcaecati dolore porro.</p> | |
<a href="#" class="read-more">Read More <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/110131/chev.png"></a> | |
</div> | |
</div> | |
</div> | |
</div> |
Following on from this tutorial this is the slider from a recent real world project
A Pen by Nick Moreton on CodePen.
// infinite slider only works with 3+ slides, so if less than 3 we need to duplicate | |
function duplicateSlides(slider, slides) { | |
if(slides.length < 3) { | |
// Duplicate slider content | |
slider.append(slider.html()); | |
// Re count slides | |
var slidesRecount = jQuery('.slider .slider__slide'); | |
// Recursive function until more than 3 slides | |
duplicateSlides(slider, slidesRecount); | |
} else { | |
// Remove active class if any already added | |
slides.removeClass('slider__slide--active'); | |
// Only add active class to first slide once recursion has finished | |
jQuery(slides[0]).addClass('slider__slide--active'); | |
} | |
} | |
jQuery(document).ready(function() { | |
var $sliderContainers = jQuery('.slider'); | |
var $body = jQuery('body'); | |
$sliderContainers.each(function() { | |
// Cache this | |
var $sliderContainer = jQuery(this); | |
// Get the inner slider for duplicate slides function | |
var $sliderInner = $sliderContainer.find('.slider__inner'); | |
// Get all the slides | |
var $slides = $sliderContainer.find('.slider__slide'); | |
// Duplicate slides | |
duplicateSlides($sliderInner, $slides); | |
// Get the background colour of the active slide | |
var bg = $sliderContainer.find('.slider__slide--active').children('.slider__slide__content').data('background'); | |
// Lighten using tinycolor | |
var lightenBy = 15; | |
var lighten = tinycolor(bg).lighten(lightenBy).toString(); | |
var lightenDouble = tinycolor(bg).lighten(lightenBy * 2).toString(); | |
// Apply lightened background color to container | |
$sliderContainer.css('background-color', lighten); | |
$body.css('background-color', lightenDouble); | |
// Move the last slide in front of the first | |
var $first = $slides.filter(':first'); | |
var $last = $slides.filter(':last'); | |
$first.before($last); | |
$sliderContainer.on('click', '.controls button', function() { | |
$slides.addClass('slider__slide--animate'); | |
var $clicked = jQuery(this); | |
var $activeSlide = $sliderContainer.find('.slider__slide--active'); | |
$first = $sliderContainer.find('.slider__slide:first'); | |
$last = $sliderContainer.find('.slider__slide:last'); | |
if($clicked.hasClass('next')) { | |
// Get the background colour of the next active slide | |
var nextBg = jQuery('.slider__slide--active').next().children('.slider__slide__content').data('background'); | |
// Lighten using tinycolor | |
var nextLighten = tinycolor(nextBg).lighten(lightenBy).toString(); | |
var nextLightenDouble = tinycolor(nextBg).lighten(lightenBy * 2).toString(); | |
// Apply lightened background color to container | |
$sliderContainer.css('background-color', nextLighten); | |
// Apply double lightened background color to body | |
$body.css('background-color', nextLightenDouble); | |
// Add active class to next slide, remove from this slide | |
$activeSlide.removeClass('slider__slide--active').next().addClass('slider__slide--active'); | |
// Move first slide to last place | |
$last.after($first); | |
} else if($clicked.hasClass('previous')) { | |
// Get the background colour of the previous active slide | |
var prevBg = jQuery('.slider__slide--active').prev().children('.slider__slide__content').data('background'); | |
// Lighten using tinycolor | |
var prevLighten = tinycolor(prevBg).lighten(lightenBy).toString(); | |
var prevLightenDouble = tinycolor(prevBg).lighten(lightenBy * 2).toString(); | |
// Apply lightened background color to container | |
$sliderContainer.css('background-color', prevLighten); | |
// Add active class to previous slide, remove from this slide | |
// Apply double lightened background color to body | |
$body.css('background-color', prevLightenDouble); | |
$activeSlide.removeClass('slider__slide--active').prev().addClass('slider__slide--active'); | |
// Move last slide to first place | |
$first.before($last); | |
} | |
}); | |
$(window).resize(function(){ | |
$slides.removeClass('slider__slide--animate'); | |
}); | |
}); | |
}); |
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.4.1/tinycolor.js"></script> |
// Breakpoints | |
@mixin breakpoint($point) { | |
@if $point==mobile { | |
@media (max-width: 767px) { | |
@content; | |
} | |
} | |
@else if $point==mobile-up { | |
@media (min-width: 768px) { | |
@content; | |
} | |
} | |
@else if $point==tablet { | |
@media (max-width: 991px) { | |
@content; | |
} | |
} | |
@else if $point==tablet-up { | |
@media (min-width: 992px) { | |
@content; | |
} | |
} | |
@else if $point==laptop { | |
@media (max-width: 1220px) { | |
@content; | |
} | |
} | |
@else if $point==laptop-up { | |
@media (min-width: 1221px) { | |
@content; | |
} | |
} | |
} | |
// Colors | |
// Monos | |
$white: #fff; | |
$light-grey: #f3f3f3; | |
$mid-grey: #e9e9e9; | |
$dark-grey: #9b9b9b; | |
$black: #2d2d2d; | |
// Brand | |
$dark-pink: #c84977; | |
$light-pink: #d692aa; | |
$dark-orange: #db5944; | |
$light-orange: #e28a7a; | |
$dark-gold: #e2c142; | |
$light-gold: #e6d8a0; | |
$dark-teal: #43cab1; | |
$light-teal: #9ed8cd; | |
$dark-blue: #466cba; | |
$light-blue: #899fce; | |
// Typography | |
$display-font: "din-2014-narrow", "Arial Narrow", Helvetica, Arial, sans-serif; | |
$body-font: "roboto", sans-serif; | |
$body-font-size: 18px; | |
body { | |
font-size: 18px; | |
transition: 0.6s; | |
padding: 0 0 50px; | |
background-color: lighten($dark-pink, 30); | |
} | |
h2, h3, h4 { | |
font-family: $display-font; | |
font-weight: 400; | |
text-transform: uppercase; | |
} | |
h2 { | |
font-size: 2em; | |
text-align: center; | |
background: $white; | |
display: inline-block; | |
padding: 2px 10px; | |
margin: 0 0 100px; | |
font-weight: 600; | |
} | |
h3 { | |
font-size: 1.4em; | |
} | |
h4 { | |
font-size: 1em; | |
} | |
.slider { | |
min-height: 300px; | |
overflow: hidden; | |
transition: 0.6s; | |
position: relative; | |
width: 100%; | |
max-width: 1200px; | |
margin:auto; | |
font-family: $body-font; | |
background-color: lighten($dark-pink, 15); | |
&__title { | |
background: $black; | |
color: $white; | |
position: absolute; | |
z-index: 9999; | |
left: calc(25% + 150px); | |
padding: 10px; | |
text-transform: uppercase; | |
font-family: $display-font; | |
@include breakpoint(mobile) { | |
left: 0; | |
} | |
h4 { | |
margin: 0; | |
} | |
} | |
.controls { | |
position: absolute; | |
z-index: 9999; | |
right: 0; | |
top: 20px; | |
height: 260px; | |
@include breakpoint(mobile) { | |
width: 100%; | |
height: 50px; | |
top: 50%; | |
transform: translateY(-50%); | |
} | |
button { | |
background: transparent; | |
border: none; | |
display: block; | |
width: 20px; | |
position: absolute; | |
padding: 0; | |
outline: none; | |
cursor: pointer; | |
&.previous { | |
top: 0; | |
right: 25px; | |
@include breakpoint(mobile-up) { | |
transform: rotate(-45deg); | |
} | |
} | |
&.next { | |
@include breakpoint(mobile-up) { | |
top: 20px; | |
right: 50px; | |
transform: rotate(135deg); | |
} | |
@include breakpoint(mobile) { | |
top: 0; | |
left: 20px; | |
transform: rotate(180deg); | |
} | |
} | |
rect { | |
fill: $black; | |
} | |
&:hover { | |
rect { | |
fill: $white; | |
} | |
} | |
} | |
} | |
&__inner { | |
width: calc(75% + 150px); | |
@include breakpoint(mobile) { | |
width: 100%; | |
} | |
max-width: 100%; | |
margin: auto; | |
position: relative; | |
min-height: 300px; | |
overflow: hidden; | |
float: right; | |
} | |
&__slide { | |
min-height: 300px; | |
width: 100%; | |
position: absolute; | |
bottom: 0; | |
left: 0; | |
transform: translate(-300px, 100%); | |
@include breakpoint(mobile) { | |
transform: translate(-100%, 0); | |
} | |
&__image { | |
position: absolute; | |
left: 150px; | |
@include breakpoint(mobile) { | |
display: none; | |
} | |
bottom: 0; | |
height: 150px; | |
width: 150px; | |
background-size: cover; | |
background-position: center; | |
} | |
&__content { | |
display: flex; | |
flex-direction: column; | |
justify-content: space-around; | |
position: absolute; | |
padding: 55px 80px 30px 30px; | |
right: 0; | |
@include breakpoint(mobile-up) { | |
right: -360px; | |
padding-right: 440px; | |
} | |
top: 0; | |
bottom: 0; | |
left: 300px; | |
@include breakpoint(mobile) { | |
padding: 55px 60px 30px; | |
left: 0; | |
background-color: transparent !important; //!important to overwrite inline style | |
} | |
h3 { | |
margin: 0; | |
} | |
p { | |
margin: 10px 0; | |
display: -webkit-box; | |
-webkit-line-clamp: 4; | |
-webkit-box-orient: vertical; | |
overflow: hidden; | |
font-size: 0.9em; | |
max-width: 600px; | |
} | |
&__categories { | |
padding: 10px 0; | |
font-family: $display-font; | |
text-transform: uppercase; | |
a { | |
color: $black; | |
text-decoration: none; | |
&:hover { | |
text-decoration: underline; | |
color: $white; | |
} | |
} | |
} | |
} | |
&--animate { | |
transition: 0.6s ease-in-out; | |
} | |
&--active { | |
transform: translate(0, 0); | |
& ~ .slider__slide { | |
transform: translate(300px, -100%); | |
@include breakpoint(mobile) { | |
transform: translate(100%, 0); | |
} | |
} | |
} | |
} | |
} | |
a.read-more { | |
background: $black; | |
padding: 5px 10px; | |
display: inline-block; | |
color: $white; | |
font-family: $display-font; | |
text-transform: uppercase; | |
align-self: flex-start; | |
margin-top: 10px; | |
text-decoration: none; | |
img { | |
max-height: 11px; | |
} | |
} |