Responsive (sort of?). Uses this technique for smooth transitions on mouse move - https://codepen.io/rachsmith/post/animation-tip-lerp
Created
September 13, 2017 08:04
-
-
Save CodeMyUI/bd172edc5309138daf6d1c8cc176bcb5 to your computer and use it in GitHub Desktop.
Smooth 3d perspective slider
This file contains hidden or 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
- var images = ["https://lh3.googleusercontent.com/aC9nyW5dhaYFmWD8fcf8DApjpH08eHEkbCHqmUPHRQ5T3jK-QyNKZYVMehmrvyPdEA_KxWvgZ3_kyOOYOAv99Ow3UoKSvEloleVKGSfLOwOyDV3Q6Dwi1G-NYoa9-t_ofmmskE6BYnVIOnIz2HWlMcijzIEwvKAL_R4z63DaLgG0z_OcGiSQHunwGAPXrBQUv42ZXuIMODq4zxDHczSxJ72b0-_udtdQK3JuT2X8nXCwFoF7GxmOpzXS0H5f50DuCbXoXcx-O7bgBMCXZdMpTxB27-wdXeLmxpYUySXgjSN2NAKmK16DmGLYvw5tMlrqwb8h4MJEEbXjP1pjPxXsahb7UZseEGyn80uLjATANJvusyJWCtzkkxYXPz-yI1rDvfEJKe2eyA-5AvFlzFBSwBMASn8f7mXinUrXMMREkJQjoi89NfZ91G7253OEVQOqcWxddiYtcHCO5v6Pl3QfV2SUTWXgggscDSY2ezjSPpYERNTXnIM_aCyWmIG7ybrfqOB0eVYBAgynyuPVbjd4KuZWZq2Dfu33HX1RuPKglbOuZGD1QbpJnruvUVkAmjDXI40ENN7X=w1600-h766","https://lh3.googleusercontent.com/4Bn4zdADhWhegRcmxS1xmHxbxIBzEgB8ADfeaCmiwT9iF7y2mN9Wc5L7gFLxUo2bgl3V-97EFrOyE9OXfkvip3pkpNxYe50GiapeT41p7D7tNJm3oEdV8Y-7toGyvz0UZ8VgDACVTUEdzzVVm2NtQSCroSvmo4gL3u0ty-KAyKnah9vIitfw2Rs1MuNzQq6vmzUcw1_4obGAKmk_Nx0dD33RSy1jbT8D61kxERbOu0pHUciywIO2EeUX8iOcJfHHQwVW3lGYcZKSiimGjBUvzHILrSpVZQ1xUlj0U21EeY4Hil1ZaJQaX47hQezcxZj7H8GyWhNv2TzQ7EU8DS3_MonCLxXlnXfk-80nncPa8DxN_UlIzJeOPDiWPSLXFaDJn_ywCutx-0onw5rcSC815_krGHXKt3L_weD5pq_e_2WI3BRZndcR2jOYLz9BiUp52ouDBIDw2OzrDtUgxne9NaQ2tOJwaIR26N1un92ChTLhXZF2F2NoS3Do96TY6A5dP6RsXQzK6G0Z6oj5XtYx-p--PrdP8wiDPAzOqXQkXbJaX8l2qPi3nTYrD8rB-eKyL2E1q9xQ=w1600-h766","https://lh3.googleusercontent.com/r29_BOXT9GjEA49-KbPtzHtTxD16dilHpFROmoJyZdQbvCelXqgG8bcApe8OgIY-avTrFOUWO-lDsmI-muMIgRVc5IFHCIyrOR18DrnwTLh70aSNY6cTY0bNbyt4QCXBlj9R4fmA8PJMRYkTA-nB5zSvlZii9NnP9kG8w__DUrYfo9IbOZAxGY_DsheGuHA0CSWLB-lQwvHo7_sSNabsiZJ2C_878r7uEfaIR6XkjcyrWMKi529UtPl9Ikln3cXphy9HrzElIL6200dGL9GHiMMoASseLp_Z950xjT2smzTrOJSADFCG9EmScicKDbFTYZH6gyc2DEP0mUFRArhTSPa4TIUwLy9KR8bG7kV-ljmSPKv4pbtH4ByXgQ5DEm5ydOkR-DTkYkLBkcFL8cjiBPPuUdK3xkjoOciwjglMF5xAXhpnTj0VUnk3RWc9YDD-AQI2uvDatV_Ae0zzLQUIm2gfV3QiDXdkkzeLWsRmCXrr0bFf42s_1NrWD0GLfrTtHNqzBCfYbAWtjeBxHfMxlESqJLAvGketLMscx5PndptC0MRhGZESjWdRUE3kNxg7PA9EhTZg=w1600-h766","https://lh3.googleusercontent.com/7MsdX710gvwl8YRxuiPIlIbGP8d3ypDASWqIOad9SpHHAPwMATjCoftyvoHjpy9eeD8aJVxVup-Zb02QMeBSFOXyqOlVc8ib3TVIXtktozy6sJK07H8Jo8UlJSpYcfgUq83Z5rJOiGQQAaZPhRYUcCR0aenU8Eh8aTuqvttfZA-PjsU39q5_I1HcpWDF1mXIxJTmlGqsoQNIuL75GDE-I2im2tAjEk6bkJkJEbDntxB5cLJEfV8TuKRsQwenkiN5opF4ttHGXYtJlS7adu-IO4wVIFcEOzdx4c1Eri3O6f9qjsTpXQH3BmpkTaLAtL5xzJit9qa0a4Dp-aZOZp1QzWeB6-dLM5HRxSiPFkku3S1umwm_GBeY3glxd3Ftata1mFIxpis6gR76oTiNO33vjxn1UZXYhCQUDByGyyuE6WOoPtu9iXJxfmUF9UMXiXVl7qyH-U7NJmq18qcU0Q6U7H3VucD_d2Vg8WTZmqVq7aA4jQ7MLuQASgMZIerxgwV_aW98z7xsS8isHgF9rN4Qtez18OjyabQxRXlC6shvRTqTDCpt1MPlfBWwyR2BKO3dHzk7h8T5=w1600-h766","https://lh3.googleusercontent.com/lqd5x1eNHsfzWpPeHNPe4u-ycQh1LyxWLp_mXi8tLvQGh4aNCbANfSfSWQdqhQy7c2J2V3a4dGIw6tRcMJCpFvsRrLLpXcFgHIjWpCWoxtgWC--0tMjb6W-YYKJX55zIhS1omxmSGPuQx1sZtsAL-XnRiqXbEIjGX1A_vbDObqVEc8TP3nVsraN5xLtektJbccNriwqqZ2CqpiuHagXKCRt3oa7D8N2ZygR-i04o8YP2pHr6I0Z76R6lZj1HDY65Sj-mkPJpN6nWKY-V_6htmMndJRY615MHntdsfZ82k5_IBbJXxdIN5MjJvgk41eyFXxzTKIXSGms-itEbW7FqMlZT8bIAigDoXYub9rh-FjtfdmVRVdwIIngzFzJrJQBroyHPxW9kW2JjH8foZCzX5YMStsHvfm1s4uAhZtbwK4KI_-x9GuXI3-cCUmtuFdQ-E2z_l3Hom57dasvYj6tFcqhRS9X_popdYTxR-4IeSE-NAjp71LDevvejtAqQTvpIRMFhV9um8qOb-xkPRe0xSoR6-chA2cQE--cbFJiLxe6ywBIqW6lI-aSI9Kv924s-OfRUGz0u=w1600-h766"]; | |
- var text = {Forest: '“And into the forest I go, to lose my mind and find my soul”', Lake: '“Mist to mist, drops to drops. For water thou art, and unto water shalt thou return”', Cliffs: '“Go to the edge of the cliff and jump off. Build your wings on the way down”', Mountains: '“What are men to rocks and mountains?”', Peaks: '“On all the peaks lies peace”'}; | |
#slider.slider(style="--img-prev:url(" + images[0] + ");") | |
#slider-content.slider__content | |
.slider__images | |
each val, i in images | |
- var imgClassName = 'slider__images-item'; | |
if i+1 === 1 | |
- imgClassName += ' slider__images-item--active'; | |
div(class=imgClassName data-id=i+1) | |
img(src=val) | |
.slider__text | |
- var i = 0; | |
each val, key in text | |
- var textClassName = 'slider__text-item'; | |
if ++i === 1 | |
- textClassName += ' slider__text-item--active'; | |
div(class=textClassName data-id=i) | |
.slider__text-item-head | |
h3= key | |
.slider__text-item-info | |
p= val | |
.slider__nav | |
.slider__nav-arrows | |
#left.slider__nav-arrow.slider__nav-arrow--left to left | |
#right.slider__nav-arrow.slider__nav-arrow--right to right | |
#slider-dots.slider__nav-dots | |
- var i = 0; | |
while i++ < images.length | |
- var dotsClassName = 'slider__nav-dot'; | |
if i === 1 | |
- dotsClassName += ' slider__nav-dot--active'; | |
div(class=dotsClassName data-id=i) | |
This file contains hidden or 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
/* | |
More about this function - | |
https://codepen.io/rachsmith/post/animation-tip-lerp | |
*/ | |
function lerp({ x, y }, { x: targetX, y: targetY }) { | |
const fraction = 0.2; | |
x += (targetX - x) * fraction; | |
y += (targetY - y) * fraction; | |
return { x, y }; | |
} | |
class Slider { | |
constructor (el) { | |
const imgClass = this.IMG_CLASS = 'slider__images-item'; | |
const textClass = this.TEXT_CLASS = 'slider__text-item'; | |
const activeImgClass = this.ACTIVE_IMG_CLASS = `${imgClass}--active`; | |
const activeTextClass = this.ACTIVE_TEXT_CLASS = `${textClass}--active`; | |
this.el = el; | |
this.contentEl = document.getElementById('slider-content'); | |
this.onMouseMove = this.onMouseMove.bind(this); | |
// taking advantage of the live nature of 'getElement...' methods | |
this.activeImg = el.getElementsByClassName(activeImgClass); | |
this.activeText = el.getElementsByClassName(activeTextClass); | |
this.images = el.getElementsByTagName('img'); | |
document.getElementById('slider-dots') | |
.addEventListener('click', this.onDotClick.bind(this)); | |
document.getElementById('left') | |
.addEventListener('click', this.prev.bind(this)); | |
document.getElementById('right') | |
.addEventListener('click', this.next.bind(this)); | |
window.addEventListener('resize', this.onResize.bind(this)); | |
this.onResize(); | |
this.length = this.images.length; | |
this.lastX = this.lastY = this.targetX = this.targetY = 0; | |
} | |
onResize () { | |
const htmlStyles = getComputedStyle(document.documentElement); | |
const mobileBreakpoint = htmlStyles.getPropertyValue('--mobile-bkp'); | |
const isMobile = this.isMobile = matchMedia( | |
`only screen and (max-width: ${mobileBreakpoint})` | |
).matches; | |
this.halfWidth = innerWidth / 2; | |
this.halfHeight = innerHeight / 2; | |
this.zDistance = htmlStyles.getPropertyValue('--z-distance'); | |
if (!isMobile && !this.mouseWatched) { | |
this.mouseWatched = true; | |
this.el.addEventListener('mousemove', this.onMouseMove); | |
this.el.style.setProperty( | |
'--img-prev', | |
`url(${this.images[+this.activeImg[0].dataset.id - 1].src})` | |
); | |
this.contentEl.style.setProperty('transform', `translateZ(${this.zDistance})`); | |
} else if (isMobile && this.mouseWatched) { | |
this.mouseWatched = false; | |
this.el.removeEventListener('mousemove', this.onMouseMove); | |
this.contentEl.style.setProperty('transform', 'none'); | |
} | |
} | |
getMouseCoefficients ({ pageX, pageY } = {}) { | |
const halfWidth = this.halfWidth; | |
const halfHeight = this.halfHeight; | |
const xCoeff = ((pageX || this.targetX) - halfWidth) / halfWidth; | |
const yCoeff = (halfHeight - (pageY || this.targetY)) / halfHeight; | |
return { xCoeff, yCoeff } | |
} | |
onMouseMove ({ pageX, pageY }) { | |
this.targetX = pageX; | |
this.targetY = pageY; | |
if (!this.animationRunning) { | |
this.animationRunning = true; | |
this.runAnimation(); | |
} | |
} | |
runAnimation () { | |
if (this.animationStopped) { | |
this.animationRunning = false; | |
return; | |
} | |
const maxX = 10; | |
const maxY = 10; | |
const newPos = lerp({ | |
x: this.lastX, | |
y: this.lastY | |
}, { | |
x: this.targetX, | |
y: this.targetY | |
}); | |
const { xCoeff, yCoeff } = this.getMouseCoefficients({ | |
pageX: newPos.x, | |
pageY: newPos.y | |
}); | |
this.lastX = newPos.x; | |
this.lastY = newPos.y; | |
this.positionImage({ xCoeff, yCoeff }); | |
this.contentEl.style.setProperty('transform', ` | |
translateZ(${this.zDistance}) | |
rotateX(${maxY * yCoeff}deg) | |
rotateY(${maxX * xCoeff}deg) | |
`); | |
if (this.reachedFinalPoint) { | |
this.animationRunning = false; | |
} else { | |
requestAnimationFrame(this.runAnimation.bind(this)); | |
} | |
} | |
get reachedFinalPoint () { | |
const lastX = ~~this.lastX; | |
const lastY = ~~this.lastY; | |
const targetX = this.targetX; | |
const targetY = this.targetY; | |
return (lastX == targetX || lastX - 1 == targetX || lastX + 1 == targetX) | |
&& (lastY == targetY || lastY - 1 == targetY || lastY + 1 == targetY); | |
} | |
positionImage ({ xCoeff, yCoeff }) { | |
const maxImgOffset = 1; | |
const currentImage = this.activeImg[0].children[0]; | |
currentImage.style.setProperty('transform', ` | |
translateX(${maxImgOffset * -xCoeff}em) | |
translateY(${maxImgOffset * yCoeff}em) | |
`); | |
} | |
onDotClick ({ target }) { | |
if (this.inTransit) return; | |
const dot = target.closest('.slider__nav-dot'); | |
if (!dot) return; | |
const nextId = dot.dataset.id; | |
const currentId = this.activeImg[0].dataset.id; | |
if (currentId == nextId) return; | |
this.startTransition(nextId); | |
} | |
transitionItem (nextId) { | |
function onImageTransitionEnd (e) { | |
e.stopPropagation(); | |
nextImg.classList.remove(transitClass); | |
self.inTransit = false; | |
this.className = imgClass; | |
this.removeEventListener('transitionend', onImageTransitionEnd); | |
} | |
const self = this; | |
const el = this.el; | |
const currentImg = this.activeImg[0]; | |
const currentId = currentImg.dataset.id; | |
const imgClass = this.IMG_CLASS; | |
const textClass = this.TEXT_CLASS; | |
const activeImgClass = this.ACTIVE_IMG_CLASS; | |
const activeTextClass = this.ACTIVE_TEXT_CLASS; | |
const subActiveClass = `${imgClass}--subactive`; | |
const transitClass = `${imgClass}--transit`; | |
const nextImg = el.querySelector(`.${imgClass}[data-id='${nextId}']`); | |
const nextText = el.querySelector(`.${textClass}[data-id='${nextId}']`); | |
let outClass = ''; | |
let inClass = ''; | |
this.animationStopped = true; | |
nextText.classList.add(activeTextClass); | |
el.style.setProperty('--from-left', nextId); | |
currentImg.classList.remove(activeImgClass); | |
currentImg.classList.add(subActiveClass); | |
if (currentId < nextId) { | |
outClass = `${imgClass}--next`; | |
inClass = `${imgClass}--prev`; | |
} else { | |
outClass = `${imgClass}--prev`; | |
inClass = `${imgClass}--next`; | |
} | |
nextImg.classList.add(outClass); | |
requestAnimationFrame(() => { | |
nextImg.classList.add(transitClass, activeImgClass); | |
nextImg.classList.remove(outClass); | |
this.animationStopped = false; | |
this.positionImage(this.getMouseCoefficients()); | |
currentImg.classList.add(transitClass, inClass); | |
currentImg.addEventListener('transitionend', onImageTransitionEnd); | |
}); | |
if (!this.isMobile) | |
this.switchBackgroundImage(nextId); | |
} | |
startTransition (nextId) { | |
function onTextTransitionEnd(e) { | |
if (!e.pseudoElement) { | |
e.stopPropagation(); | |
requestAnimationFrame(() => { | |
self.transitionItem(nextId); | |
}); | |
this.removeEventListener('transitionend', onTextTransitionEnd); | |
} | |
} | |
if (this.inTransit) return; | |
const activeText = this.activeText[0]; | |
const backwardsClass = `${this.TEXT_CLASS}--backwards`; | |
const self = this; | |
this.inTransit = true; | |
activeText.classList.add(backwardsClass); | |
activeText.classList.remove(this.ACTIVE_TEXT_CLASS); | |
activeText.addEventListener('transitionend', onTextTransitionEnd); | |
requestAnimationFrame(() => { | |
activeText.classList.remove(backwardsClass); | |
}); | |
} | |
next () { | |
if (this.inTransit) return; | |
let nextId = +this.activeImg[0].dataset.id + 1; | |
if (nextId > this.length) | |
nextId = 1; | |
this.startTransition(nextId); | |
} | |
prev () { | |
if (this.inTransit) return; | |
let nextId = +this.activeImg[0].dataset.id - 1; | |
if (nextId < 1) | |
nextId = this.length; | |
this.startTransition(nextId); | |
} | |
switchBackgroundImage (nextId) { | |
function onBackgroundTransitionEnd (e) { | |
if (e.target === this) { | |
this.style.setProperty('--img-prev', imageUrl); | |
this.classList.remove(bgClass); | |
this.removeEventListener('transitionend', onBackgroundTransitionEnd); | |
} | |
} | |
const bgClass = 'slider--bg-next'; | |
const el = this.el; | |
const imageUrl = `url(${this.images[+nextId - 1].src})`; | |
el.style.setProperty('--img-next', imageUrl); | |
el.addEventListener('transitionend', onBackgroundTransitionEnd); | |
el.classList.add(bgClass); | |
} | |
} | |
const sliderEl = document.getElementById('slider'); | |
const slider = new Slider(sliderEl); | |
// ------------------ Demo stuff ------------------------ // | |
let timer = 0; | |
function autoSlide () { | |
requestAnimationFrame(() => { | |
slider.next(); | |
}); | |
timer = setTimeout(autoSlide, 5000); | |
} | |
function stopAutoSlide () { | |
clearTimeout(timer); | |
this.removeEventListener('touchstart', stopAutoSlide); | |
this.removeEventListener('mousemove', stopAutoSlide); | |
} | |
sliderEl.addEventListener('mousemove', stopAutoSlide); | |
sliderEl.addEventListener('touchstart', stopAutoSlide); | |
timer = setTimeout(autoSlide, 2000); |
This file contains hidden or 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
@import url('https://fonts.googleapis.com/css?family=Lora:700'); | |
@import url('https://fonts.googleapis.com/css?family=Open+Sans'); | |
$item-width: 65vw; | |
$transition-time: .7s; | |
$transition-text-time: $transition-time / 2; | |
$offset: 1em; | |
$mobile-bkp: 650px; | |
:root { | |
--z-distance: $item-width / 7.63; | |
--from-left: 1; | |
--mobile-bkp: $mobile-bkp; | |
} | |
*, *::before, *::after { | |
box-sizing: border-box; | |
} | |
body { | |
min-height: 100vh; | |
margin: 0; | |
padding: 0; | |
overflow: hidden; | |
font-family: Lora, serif; | |
font-size: calc(14px + .3vw); | |
} | |
.slider { | |
width: 100vw; | |
height: 100vh; | |
display: flex; | |
perspective: 1000px; | |
transform-style: preserve-3d; | |
&::before, &::after { | |
content: ''; | |
left: -1vw; | |
top: -1vh; | |
display: block; | |
position: absolute; | |
width: 102vw; | |
height: 102vh; | |
background-position: center; | |
background-size: cover; | |
will-change: opacity; | |
// uncomment ↓ if you want to kill your processor | |
// filter: blur(.2em); | |
z-index: -1; | |
box-shadow: 0 0 0 50vmax hsla(0, 50%, 0, .7) inset; | |
} | |
&::before { | |
background-image: var(--img-prev); | |
} | |
&::after { | |
transition: opacity $transition-time; | |
opacity: 0; | |
background-image: var(--img-next); | |
} | |
&--bg-next::after { | |
opacity: 1; | |
} | |
&__content { | |
margin: auto; | |
width: $item-width; | |
height: $item-width / 2; | |
max-height: 60vh; | |
will-change: transform; | |
transform-style: preserve-3d; | |
pointer-events: none; | |
transform: translateZ(var(--z-distance)); | |
} | |
&__images { | |
overflow: hidden; | |
position: absolute; | |
width: 100%; | |
height: 100%; | |
z-index: 0; | |
box-shadow: 0 0 5em #000; | |
&-item { | |
position: absolute; | |
top: 0; | |
left: 0; | |
height: 100%; | |
width: 100%; | |
will-change: transform; | |
transition-timing-function: ease-in; | |
visibility: hidden; | |
img { | |
display: block; | |
position: relative; | |
left: -$offset; | |
top: -$offset; | |
width: calc(100% + #{$offset} * 2); | |
height: calc(100% + #{$offset} * 2); | |
object-fit: cover; | |
will-change: transform; | |
} | |
} | |
&-item--active { | |
z-index: 20; | |
visibility: visible; | |
} | |
&-item--subactive { | |
z-index: 15; | |
visibility: visible; | |
} | |
&-item--next { | |
transform: translateX(100%); | |
} | |
&-item--prev { | |
transform: translateX(-100%); | |
} | |
&-item--transit { | |
transition: transform $transition-time, opacity $transition-time; | |
} | |
} | |
&__text { | |
position: relative; | |
height: 100%; | |
&-item { | |
position: absolute; | |
width: 100%; | |
height: 100%; | |
padding: 0.5em; | |
perspective: 1000px; | |
transform-style: preserve-3d; | |
> * { | |
overflow: hidden; | |
position: absolute; | |
} | |
h3, & p { | |
transition: transform $transition-text-time ease-out; | |
line-height: 1.5; | |
overflow: hidden; | |
} | |
h3 { | |
background-color: hsla(0, 50%, 100%, 0.5); | |
} | |
p { | |
font-family: 'Open Sans', sans-serif; | |
padding: 1em; | |
color: white; | |
text-align: center; | |
background-color: hsla(0, 0%, 0%, 0.5); | |
} | |
h3::before, & p::before { | |
content: ''; | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
transform: translateX(0); | |
transition: transform | |
$transition-text-time | |
ease-out | |
$transition-text-time * .8; | |
} | |
h3::before { | |
background-color: #000; | |
} | |
p::before { | |
background-color: #fff; | |
} | |
h3 { | |
margin: 0; | |
font-size: 3.5em; | |
padding: 0 .3em; | |
position: relative; | |
font-weight: 700; | |
transform: translateX(-100%); | |
} | |
p { | |
margin: 0; | |
transform: translateX(100%); | |
} | |
} | |
&-item-head { | |
top: -0.5em; | |
transform: translateZ(3em); | |
clip-path: polygon(0 0, .5em 100%, 100% 100%, calc(100% - .3em) .3em); | |
} | |
&-item-info { | |
bottom: 0; | |
right: 0; | |
max-width: 75%; | |
min-width: min-content; | |
transform: translateZ(2em); | |
clip-path: polygon(0.5em 0, 100% 0%, calc(100% - .5em) 100%, 0 calc(100% - .5em)); | |
} | |
&-item--active { | |
h3, & p { | |
transform: translateX(0); | |
} | |
h3::before { | |
transform: translateX(100%); | |
} | |
p::before { | |
transform: translateX(-100%); | |
} | |
} | |
&-item--backwards { | |
h3::before, p::before { | |
transition: transform $transition-text-time ease-in; | |
} | |
h3, p { | |
transition: transform $transition-text-time ease-in $transition-text-time; | |
} | |
} | |
} | |
&__nav { | |
position: absolute; | |
left: 0; | |
top: 0; | |
width: 100%; | |
height: 100%; | |
text-align: center; | |
$arrow-size: 5vw; | |
&-arrows { | |
display: flex; | |
justify-content: space-between; | |
width: 100%; | |
position: absolute; | |
top: 0; | |
left: 0; | |
} | |
&-arrow { | |
height: 100vh; | |
width: 50vw; | |
text-indent: -9999px; | |
white-space: nowrap; | |
&--left { | |
--arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80' viewBox='0 0 4 4'%3E %3Cpolyline points='3 1 1 2 3 3' stroke='white' stroke-width='.3' stroke-opacity='.5' fill='none'%3E%3C/polyline%3E %3C/svg%3E"); | |
cursor: var(--arrow) 40 40, auto; | |
} | |
&--right { | |
--arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80' viewBox='0 0 4 4'%3E %3Cpolyline points='1 1 3 2 1 3' stroke='white' stroke-width='.3' stroke-opacity='.5' fill='none'%3E%3C/polyline%3E %3C/svg%3E"); | |
cursor: var(--arrow) 40 40, auto; | |
} | |
} | |
$dot-clr: hsla(0, 50%, 100%, .5); | |
$dot-size: 1em; | |
$dot-border: 2px; | |
&-dots { | |
$pad: 1em; | |
margin-top: 88vh; | |
display: inline-flex; | |
position: relative; | |
padding: $pad; | |
pointer-events: none; | |
&::before { | |
content: ''; | |
position: absolute; | |
left: calc(#{$pad} + #{$dot-size} + #{$dot-border}); | |
top: calc(#{$pad} + #{$dot-border}); | |
width: calc(#{$dot-size} - #{$dot-border} * 2); | |
height: calc(#{$dot-size} / 2 - #{$dot-border} * 2); | |
background-color: hsla(0, 50%, 100%, .9); | |
transition: transform $transition-time ease-out; | |
transform: translateX(calc((#{$dot-size} + #{$pad} * 2) * (var(--from-left) - 1))); | |
} | |
} | |
&-dot { | |
margin: 0 $dot-size; | |
width: $dot-size; | |
height: $dot-size / 2; | |
border: $dot-border solid $dot-clr; | |
/* | |
The cursor is not the default one because of a weird bug | |
related to custom cursors above | |
*/ | |
cursor: crosshair; | |
pointer-events: all; | |
display: inline-block; | |
&:hover { | |
border-color: hsla(0, 50%, 100%, .7); | |
} | |
&:active { | |
border-color: $dot-clr; | |
} | |
} | |
} | |
} | |
@media only screen and (max-width: $mobile-bkp) { | |
.slider::before, | |
.slider::after { | |
display: none; | |
} | |
.slider__content { | |
width: 100vw; | |
height: 100vh; | |
max-height: 100vh; | |
} | |
.slider__text-item-info { | |
bottom: 50%; | |
left: 50%; | |
transform: translate(-50%, 50%); | |
p { | |
padding: 1em .8em; | |
} | |
} | |
.slider__text-item-head { | |
top: 5vh; | |
left: 10vw; | |
transform: translateZ(0); | |
h3 { | |
font-size: 2.5em; | |
} | |
} | |
.slider__nav-dots { | |
background-color: hsla(0,50%,0%,.3); | |
} | |
.slider__nav-arrow { | |
width: 10vw; | |
position: relative; | |
cursor: auto; | |
&:active { | |
filter: brightness(.5); | |
} | |
&::before { | |
content: ''; | |
background-image: var(--arrow); | |
background-size: cover; | |
width: 8vw; | |
height: 8vw; | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
} | |
&--left { | |
background-image: linear-gradient(to right, hsla(0,50%,0%,.7) 0, transparent 100%); | |
&:active { | |
background-image: linear-gradient(to right, hsla(0,50%,0%,.9) 0, transparent 100%); | |
} | |
} | |
&--right { | |
background-image: linear-gradient(to left, hsla(0,50%,0%,.7) 0, transparent 100%); | |
&:active { | |
background-image: linear-gradient(to left, hsla(0,50%,0%,.9) 0, transparent 100%); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment