Created
October 21, 2017 20:10
-
-
Save ohsoren/32981efd7e483a44663272854f2598ad to your computer and use it in GitHub Desktop.
Horizontal Centered Slider Hearts Duo-Tone
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
HUGE SHOUTOUT to Lentie Ward | |
https://codepen.io/lentilz | |
https://codepen.io/lentilz/pen/mPOKdG | |
[thank you] | |
--> | |
<section class="sliderWrapper"> | |
<div class="slider" data-slider-moving="false"> | |
<div class="slide slide-1">1</div> | |
<div class="slide slide-2">2</div> | |
<div class="slide slide-3">3</div> | |
<div class="slide slide-4">4</div> | |
<div class="slide slide-5">5</div> | |
</div> | |
<button class="button buttonLeft">left</button> | |
<button class="button buttonRight">right</button> | |
</section> | |
<p>Next element after .sliderWrapper</p> | |
<svg class="duotone-filters" xmlns="http://www.w3.org/2000/svg"> | |
<filter id="duotone_soren"> | |
<feColorMatrix type="matrix" result="gray" | |
values="1 0 0 0 0 | |
1 0 0 0 0 | |
1 0 0 0 0 | |
0 0 0 1 0" > | |
</feColorMatrix> | |
<feComponentTransfer color-interpolation-filters="sRGB" result="duotone"> | |
<feFuncR type="table" tableValues="0.1647058824 0.2"></feFuncR> | |
<feFuncG type="table" tableValues="0.6588235294 0.2"></feFuncG> | |
<feFuncB type="table" tableValues="0.5490196078 0.2"></feFuncB> | |
<feFuncA type="table" tableValues="0 1"></feFuncA> | |
</feComponentTransfer> | |
</filter> | |
</svg> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Horizontally ceneterd slider/carousel | |
* caveat: slides are equal width | |
*/ | |
var sliderWrapper = document.querySelector('.sliderWrapper'); | |
var slider = document.querySelector(".slider"); | |
var sliderWidth, slideWidth, slideHeight, sliderSpeed = 1000; | |
var sliderDimensions = slider.getBoundingClientRect(); | |
var myWidth, left, itm, cln; | |
var buttonLeft = document.querySelector(".buttonLeft"); | |
var buttonRight = document.querySelector(".buttonRight"); | |
/** | |
* we want to keep the slider horizontally centered | |
* let's calculate shit and do stuff when window resized | |
*/ | |
function keepSliderCenter() { | |
/* we need to calculate some shit. we'll need the width and height of a slide to calculate the slider width and height; we also need the window width. the plan is to push or pull the slider into position depending on its and the windows width */ | |
// get first slide width | |
slideWidth = slider.firstElementChild.getBoundingClientRect().width; | |
// get first slide height | |
slideHeight = slider.firstElementChild.getBoundingClientRect().height; | |
// set slider width by slide width (times by number of slides) | |
slider.style.width = (slideWidth * 5) + "px"; | |
// set slider wrapper height by slide height so that any content below clears the absolute positioned slider | |
sliderWrapper.style.height = slideHeight + "px"; | |
// get window width | |
myWidth = window.innerWidth; | |
// get slider width | |
sliderWidth = slider.getBoundingClientRect().width; | |
// when we resize, if window width is equal to or greather than slider width | |
if (myWidth => sliderWidth) { | |
// push slider to center on window | |
left = (myWidth - sliderWidth) / 2; | |
slider.style.left = left + "px"; | |
} | |
else { | |
// pull slider to center of window | |
left = (sliderWidth - myWidth) / 2; | |
slider.style.left = left + "px"; | |
} | |
}; | |
/** | |
* now let's make the slider move with buttons | |
*/ | |
// we've clicked the button, the slider is about to move | |
// prepare the slider for transition | |
function sliderIsAboutToMove(ev) { | |
// disable button | |
ev.target.disabled = true; | |
// get slider dimensions in advance | |
sliderDimensions = slider.getBoundingClientRect(); | |
// get slide width in advance | |
slideWidth = slider.firstElementChild.getBoundingClientRect().width; | |
// set slider moving data attribute to true | |
slider.setAttribute('data-slider-moving', 'true'); | |
} | |
// the slider has stopped moving | |
// reset the slider to it's pre-transition state | |
function resetSlider(ev) { | |
// reset slider moving data attribute to false | |
slider.setAttribute('data-slider-moving', 'false'); | |
// move slider back to original position | |
slider.style.left = sliderDimensions.left + "px"; | |
// enable button now slider not moving | |
ev.target.disabled = false; | |
} | |
// let's do shit with left button | |
function leftButton(ev) { | |
// prepare the slider for transition | |
sliderIsAboutToMove(ev); | |
// let's go! push slider right by 1 slide width | |
slider.style.left = (sliderDimensions.left + slideWidth) + "px"; | |
// get last slide | |
itm = slider.lastElementChild; | |
// clone last slide | |
cln = itm.cloneNode(true); | |
// do slide clone shit after slider transition ends | |
setTimeout(function() { | |
// remove last slide from slider | |
itm.remove(); | |
// prepend clonded last slide to slider | |
slider.prepend(cln); | |
// slider transition has ended so reset slider | |
resetSlider(ev); | |
}, sliderSpeed) | |
} | |
// let's do pretty much the same shit with right button | |
function rightButton(ev) { | |
// prepare the slider for transition | |
sliderIsAboutToMove(ev); | |
// let's go! pull slider left by 1 slide width | |
slider.style.left = (sliderDimensions.left - slideWidth) + "px"; | |
// get first slide | |
itm = slider.firstElementChild; | |
// clone first slide | |
cln = itm.cloneNode(true); | |
// do slide clone shit after slider transition ends | |
setTimeout(function() { | |
// remove first slide from slider | |
itm.remove(); | |
// append clonded last slide to slider | |
slider.append(cln); | |
// slider transition has ended so reset slider | |
resetSlider(ev); | |
}, sliderSpeed) | |
} | |
// center on resize | |
window.onresize = keepSliderCenter; | |
// center on window load | |
window.onload = keepSliderCenter; | |
// left button event | |
buttonLeft.addEventListener("mouseup", leftButton); | |
// right button event | |
buttonRight.addEventListener("mouseup", rightButton); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
:root { | |
--slide-width: 350px; | |
--slide-width-large: 700px; | |
--slide-height: 150px; | |
--slide-height-large: 200px; | |
--slide-bg-color: darkslateblue; | |
--slide-bg-color-highlight: slateblue; | |
} | |
body { | |
position: relative; | |
background-color: #333; | |
color: #e4e4e4; | |
font-weight: 300; | |
overflow: hidden; | |
} | |
body:before { | |
content: ""; | |
display: block; | |
position: absolute; | |
top: 0; | |
bottom: 0; | |
height: 100vh; | |
left: 50%; | |
transform: translateX(-1px); | |
border-right: 2px dashed var(--slide-bg-color-highlight); | |
z-index: 20; | |
} | |
.sliderWrapper { | |
position: relative; | |
} | |
.slider { | |
position: absolute; | |
display: flex; | |
top: 0; | |
z-index: 5; | |
} | |
.slide { | |
flex: 0 0 var(--slide-width); | |
height: var(--slide-height); | |
background-size: 100% auto; | |
background-position: center; | |
text-align: center; | |
transition: background .3s; | |
z-index: 10; | |
/* filter: grayscale(100%); */ | |
-webkit-filter: url(#duotone_soren); | |
-moz-filter: url(#duotone_soren); | |
-o-filter: url(#duotone_soren); | |
-ms-filter: url(#duotone_soren); | |
filter: url(#duotone_soren); | |
} | |
@media (min-width: 900px) { | |
.slide { | |
flex: 0 0 var(--slide-width-large); | |
height: var(--slide-height-large); | |
} | |
} | |
[data-slider-moving="false"] .slide:nth-child(3n):hover { | |
filter: none; | |
} | |
.slide-1 { | |
background-image: url('http://www.vectorbackground.net/wp-content/uploads/2013/06/Landscape_007.jpg'); | |
} | |
.slide-2 { | |
background-image: url('https://previews.123rf.com/images/iimages/iimages1204/iimages120401206/13131616-Illustration-of-a-forest-Stock-Vector-forest-cartoon-jungle.jpg'); | |
} | |
.slide-3 { | |
background-image: url('http://images.all-free-download.com/images/graphiclarge/cartoon_landscape_vector_background_278494.jpg'); | |
} | |
.slide-4 { | |
background-image: url('https://images.vexels.com/media/users/2122/71333/preview2/7fab2f1c46e4208c996ddade1ede7749-forest-side-river-cartoon-landscape.jpg'); | |
} | |
.slide-5 { | |
background-image: url('https://i.pinimg.com/736x/a1/cf/0d/a1cf0d5a2af2650a58c2d809cd7b90e7--original-wallpaper-cartoon.jpg'); | |
} | |
[data-slider-moving="true"] { | |
transition: 1s; | |
} | |
.button { | |
position: absolute; | |
top: 0; | |
bottom: 0; | |
width: 44px; | |
background-color: rgba(34, 34, 34, .8); | |
border: 0; | |
z-index: 15; | |
opacity: 0; | |
text-indent: -9999px; | |
transition: opacity .35s; | |
} | |
.sliderWrapper:hover .button { | |
transition-delay: .1s; | |
opacity: 1; | |
cursor: pointer; | |
} | |
.buttonLeft { | |
left: 0; | |
} | |
.buttonRight { | |
right: 0; | |
} | |
.button:after { | |
content: ""; | |
display: block; | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
width: 20px; | |
height: 20px; | |
background-color: slateblue; | |
} | |
.button[disabled], | |
.button[disabled]:hover { | |
opacity: .5; | |
} | |
.duotone-filters { | |
height: 0; | |
left: -9999em; | |
margin: 0; | |
padding: 0; | |
position: absolute; | |
width: 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment