JSFiddle - React, Tailwind, and code Playground
by Ronny
HTML
<script src="https://rawgit.com/utatti/perfect-scrollbar/master/dist/perfect-scrollbar.js"></script>
<link rel="stylesheet" href="https://rawgit.com/utatti/perfect-scrollbar/master/css/perfect-scrollbar.css">
<div id="hideScroll">
<div id="scrollable" class="outer">
<div id="content" class="inner">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Laudantium quos dolorum voluptatum, alias placeat modi illum itaque aspernatur ut, odio a neque facilis iure architecto tempore culpa amet velit. Eius.
</div>
</div>
</div>
<div id="scroller1" class="outer scrollbar">
<div class="inner"></div>
</div>
<div id="scroller2" class="outer scrollbar">
<div class="inner"></div>
</div>
<div id="scroller3" class="outer scrollbar">
<div class="inner"></div>
</div>
<div id="scroller4" class="outer scrollbar">
<div class="inner"></div>
</div>
CSS
:root {
--container-width: 400px;
--scrollable-width: 600px;
--scrollable-height: 100px;
}
.inner {
width: var(--scrollable-width);
height: 10px;
}
.outer {
width: var(--container-width);
overflow-x: auto;
height: 100%;
position: relative;
}
#content {
background: #88f;
height: var(--scrollable-height);
}
#hideScroll {
overflow: hidden;
}
#scroller1 {
margin-top: 10px;
transform: scaleX(.3);
transform-origin: 0 0;
border-radius: 10px 5px 2em / 20px 25px 30%;
}
#scroller2 {
margin-top: 10px;
transform-origin: 0 0;
}
#scroller3 {
margin-top: 10px;
transform: scaleX(2);
transform-origin: 0 0;
}
#scroller4 {
margin-top: 10px;
transform: rotate(45deg);
transform-origin: 0 100%;
}
.ps__rail-x {
opacity: 1;
}
.ps__thumb-x {
border-radius: 20px;
}
.ps__rail-x:hover .ps__thumb-x,
.ps__thumb-x {
height: 12px;
bottom: 3px;
}
JavaScript
var ps = new PerfectScrollbar('#scroller1.scrollbar');
var ps2 = new PerfectScrollbar('#scroller2.scrollbar');
var ps3 = new PerfectScrollbar('#scroller3.scrollbar');
var ps4 = new PerfectScrollbar('#scroller4.scrollbar');
// Get scrollbar size of current browser & os
const scrollHeight = scrollable.offsetHeight - content.offsetHeight
// Gett all scrollbar elements
const scrollbars = Array.from(document.querySelectorAll('.scrollbar'))
// Hide the scrollbar of content
hideScroll.style.height = `${content.offsetHeight}px`
scrollbars.forEach(scrollbar => {
// Set custom scrollbar element height to be scrollbar height
// Had to add '1' because chrome is weird with 0 height
scrollbar.style.height = `${scrollHeight + 1}px`
// Listen to both scrolls and change only if scroll is not equal
scrollbar.addEventListener('scroll', syncScroll)
})
// Listen to main element scrolls and change only if scroll is not equal
scrollable.addEventListener('scroll', syncScroll)
function syncScroll(event) {
if (scrollbars.some(scrollbar => scrollbar.scrollLeft !== scrollable.scrollLeft)) {
scrollable.scrollTo(event.target.scrollLeft, 0)
scrollbars.forEach(scrollbar => scrollbar.scrollTo(event.target.scrollLeft, 0))
}
}
if (!scrollHeight) {
document.body.innerHtml += 'Your scrollbars are hidden, you are probably on a mac with "auto" scrollbars'
}