Slide prototype 3

by Julien Etienne

HTML

<section>

  <div class="navs" id="navs">
    <nav id="list">
      <div class="one">One</div>
      <div class="two">Two</div>
      <div class="three">Three</div>
      <div class="four">Four</div>
      <div class="five">Five</div>
      <div class="six">Six</div>
    </nav>
  </div>

</section>
<aside>
  <button id="prev">Prev</button><button id="next">Next</button>
</aside>



<div id="direct">
  <button id="0">1</button>
  <button id="1">2</button>
  <button id="2">3</button>
  <button id="3">4</button>
  <button id="4">5</button>
  <button id="5">6</button>
</div>

CSS

body {
  display: grid;
  justify-content: center;
  --width: 200px
}

section {
  width: 300px;
  height: 100px;
  border: 4px solid crimson;
  position: relative;
  overflow: hidden;
  left: calc(var(--width) * -1);
}

.navs {
  /*  display: grid; */
  grid-auto-flow: column;
  position: absolute;
  width: calc(200px * 6 * 3);
/*   left: calc(200px * -6); */
margin-left: 50px;
  height: 100px;
  border: 1px solid lime;
  display: inline;
}

nav {
  display: grid block;
  grid-auto-flow: column;
  height: 100px;
  transform-origin: 50% 50%;
  transition: all 400ms ease;
  /* position: absolute; */
  float: left;
  position: relative;
  /* border: 1px solid blue; */

  >.one {
    background: lightblue;
  }

  >.two {
    background: lightgreen;
  }

  >.three {
    background: lightgray;
  }

  >.four {
    background: lightyellow;
  }

  >.five {
    background: lightpink;
  }

  >.six {
    background: orange;
  }
}

nav:nth-child(1) {}

/* nav:nth-child(2) {
  display: none;
} */

div {
  width: 200px;
  height: 100px;
  font-size: 3rem;
  display: grid;
  justify-content: center;
  align-content: center;
}

#prev,
#next {
  display: inline;
  margin-top: 2rem;
}

JavaScript

const main = document.querySelector('#list')
const navs = document.querySelector('#navs')
const leftPad = main.cloneNode(true)

leftPad.removeAttribute('id')

const wrapper = [leftPad, main]
if (leftPad.children.length <= 5) wrapper.push(leftPad.cloneNode(true))
navs.append(...wrapper)

const lists = Array.from(navs.children)
const items = wrapper.map(nav => Array.from(nav.children))
const items1Length = items[1].length
const oItems = Array.from(items[1])
const prev = document.querySelector('#prev')
const next = document.querySelector('#next')
const width = 200
const height = 100
const displace = -2
let index = 0

const transitionStyle = 'all 200ms ease'
let transform = 0

const navWidth = navs.children[1].getBoundingClientRect().width

const transformAction = transformValue => el => el.style.transform = `translate3d(${transformValue}px,0,0)`
const transitionAction = value => el => el.style.transition = value

navs.style.left = -(navWidth + (width * -displace)) + 'px'

const rotate = (amount, transition = true) => {
  const i = items[1].findIndex(item => item === oItems[amount])
  amount = -(i + displace)

  items.forEach((item, i) => items[i] = [...items[i].slice(-amount), ...items[i].slice(0, -amount)])

  wrapper.forEach((navEl, i) => navEl.append(...items[i]))
  if (!transition) return

  transform -= width * amount
  wrapper.forEach(transitionAction('none'))
  wrapper.forEach(transformAction(transform))

  window.requestAnimationFrame(() => {
    wrapper.forEach(transitionAction(transitionStyle))
    transform += width * amount
    wrapper.forEach(transformAction(transform))
  })
}

rotate(0, false)

document.addEventListener('mousedown', ({
  target
}) => {
  if (target === next) index++
  if (target === prev) index--
  index = index % items1Length
  if (index < 0) index += items1Length

  if (target.closest('#direct') && target.tagName === 'BUTTON') {
    index = parseFloat(target.id)
    rotate(index)
    return
  }

  if (target === next || target ===...