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)