JSFiddle - React, Tailwind, and code Playground

by Константин Дралюк

HTML

<div class='news-ticker'>
  <div class="news-ticker__inner">
    <div class="news-ticker__list" data-js='news-ticker'>
      <div class='news-ticker__item'>Lorem ipsum dolor sit amet!</div>
      <div class='news-ticker__item'>Lorem ipsum dolor sit amet!</div>
  </div>
</div>

SCSS

body {
  margin: 0;
  font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
}

.news-ticker {
  background: #ccc;
  &, * {
    box-sizing: border-box;
  }
  &__inner {
    padding: 0 1rem;
  }
  &__list {
    display: flex;
    align-items: flex-start;
    overflow: hidden;
  }
  &__item {
    white-space: nowrap;
    padding: 1.5rem .75rem;
    display: block;
    user-select: none;
  }
}

JavaScript

const $js = (selector) => document.querySelector(`[data-js='${selector}']`)
const $nt = $js('news-ticker')

let isStopped = false

$nt.onmouseover = () => isStopped = true
$nt.onmouseout = () => isStopped = false

const move = () => {
	const $children = [...$nt.children]
  const $first = $children.slice(1)[0]
  const $last = $children.slice(-1)[0]
	const scrollViewWidth = $nt.scrollWidth - $nt.offsetWidth
  const isScrollable = scrollViewWidth > 0
  const needsCloning = scrollViewWidth < $first.offsetWidth + $last.offsetWidth

  if (!isScrollable) {
  	$nt.scrollLeft = 0
  }

  if (isStopped || !isScrollable) {
  	return false
  }
  
  $children.map($el => {
    const $cloned = $el.cloneNode(true)
    $cloned.className += ' -cloned'
    return $nt.appendChild($cloned)
  })

  if (needsCloning) {
    [...$children].map($el => {
    	const $cloned = $el.cloneNode(true)
      $cloned.className += ' -cloned'
      return $nt.appendChild($cloned)
    })
  }
  
  if ($nt.scrollLeft < scrollViewWidth) {
		$nt.scrollLeft += 1
  } else {
    $nt.scrollLeft -= $first.offsetWidth
    $nt.appendChild($first)
  }
}

setInterval(move, 10)