Reputation: 69
I have a custom scrollbar that I only want visible when the mouse is moved on the page (entire body, not just within the #scrolling-wrapper) or the div #scrolling-wrapper is scrolled. When the mouse has been still for ~1 second (or however long is the default for typical scrollbars) and there has been no scrolling, the scrollbar should fade out. It should work like a default auto hiding scrollbar, but with my custom styling. The only difference is that it should also appear when the mouse is moved rather than only when the div is scrolled as users with a mouse will not be able to scroll within the horizontal div with their mouse wheel... thus needing the scrollbar to appear when the mouse is moved.
Here is a JSFiddle (https://jsfiddle.net/jde7s1kr/) that features @nidhin-joseph's solution, which is close but it does not work correctly 100% of the time like I need it to. Sometimes the scrollbar will not appear on mouse move or scroll and sometimes it does not disappear. The code is also forcing the videos to slightly jump up and down at times (a problem that was not occurring prior to adding the JS events to show / hide the scrollbar). I'm assuming this has to do with the scrollbar appearing and forcing the videos upwards slightly. This cannot happen either.
So to clarify: when a mouse is moved or the div is scrolled I need the scrollbar visible and whenever either of those two actions do not occur for ~1 second, the scrollbar can fade out.
Code:
<div id="horizontalcontainer">
<div id="scrolling-wrapper">
<div class="videocard1">
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://www.youtube.com/embed/_OBlgSz8sSM" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
<div class="videocard">
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://www.youtube.com/embed/_OBlgSz8sSM" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
<div class="videocardlast">
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://www.youtube.com/embed/_OBlgSz8sSM" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
</div>
</div>
::-webkit-scrollbar {
height: 2%;
display: var(--scroll-display);
}
:root {
--scroll-display: none;
}
/* Track */
::-webkit-scrollbar-track {
background: transparent;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: black;
border-radius: 25px;
}
#horizontalcontainer {
z-index: 0;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
}
#scrolling-wrapper {
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
text-align: center;
margin: 0 auto;
height: 100vh;
width: 100vw;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: none;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.videocard1 {
padding-left: 27%;
padding-right: 2.5%;
display: inline-block;
width: 46.5%;
top: 50%;
transform: translateY(-50%);
}
.videocard {
padding-right: 2.5%;
display: inline-block;
position: relative;
width: 46.5%;
top: 50%;
transform: translateY(-50%);
}
.videocardlast {
padding-right: 27%;
display: inline-block;
position: relative;
width: 46.5%;
top: 50%;
transform: translateY(-50%);
}
Thanks!
Upvotes: 3
Views: 2871
Reputation: 336
With the details you submitted, This solution offer you the customization you want for your famous custom scrollbar. This solution offer browser compatibility. This solution offer css only or Css + jS callback
Found issues in your code You want it compatible with 100% browser but use specific Webkit Css? By default scroll-bars takes +/- 20px of the viewport it usualy need to be taken into accounts? That's why content jump around when you show/hide default overflow scrollbars. It's not a bug it's a feature. Only on mobile the standard scroll is over the content.
So to fullfill your requirements. Here's what you need to do, use a framework that take into account the multiple caveats of the different browser, if not you'll be tweaking Javascript and Css forever each time to test it in a new browser. In this case here ill Be Using SimpleBar to allow you customization And use Jquery to trigger SimpleBar Into Action And set the timeout to "2000" miliseconds This will work in modern browser '100% of the time'.
Simplebar https://github.com/Grsmto/simplebar/tree/master/packages/simplebar
Working JSfiddle https://jsfiddle.net/ft9h210g/12/
HTML
<head>
<link rel="stylesheet" href="https://unpkg.com/simplebar@latest/dist/simplebar.css" />
</head>
<body>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous"></script>
<script src="https://unpkg.com/simplebar@latest/dist/simplebar.min.js"></script>
<div id="horizontalcontainer">
<div id="scrolling-wrapper">
<div class="videocard1">
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://www.youtube.com/embed/_OBlgSz8sSM" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
<div class="videocard">
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://www.youtube.com/embed/_OBlgSz8sSM" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
<div class="videocard">
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://www.youtube.com/embed/_OBlgSz8sSM" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
<div class="videocardlast">
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://www.youtube.com/embed/_OBlgSz8sSM" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
</div>
</div>
</body>
JS
const simplebar = new SimpleBar(document.querySelector('#scrolling-wrapper'), {
autoHide: true,
timeout: 2000
});
css
.hidden {
display: none;
}
#container {
width: 200px;
}
#scrollable {
height: 200px;
}
.simplebar {
position: relative;
z-index: 0;
overflow: hidden;
-webkit-overflow-scrolling: touch;
}
::-webkit-scrollbar {
height: 1%;
display: var(--scroll-display);
}
:root {
--scroll-display: none;
}
#horizontalcontainer {
z-index: 0;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: 100%;
/*
height: 100%;
*/
height: 400px;
display: flex;
align-items: center;
}
#scrolling-wrapper {
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
text-align: center;
margin: 0 auto;
height: 250px;
width: 100vw;
/*
-webkit-overflow-scrolling: touch;
-ms-overflow-style: none;
*/
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.videocard1 {
padding-left: 27%;
padding-right: 2.5%;
display: inline-block;
position: relative;
width: 46.5%;
/* top: 50%;
transform: translateY(-50%); */
}
.videocard {
padding-right: 2.5%;
display: inline-block;
position: relative;
width: 46.5%;
/* top: 50%;
transform: translateY(-50%); */
}
.videocardlast {
padding-right: 27%;
display: inline-block;
position: relative;
width: 46.5%;
/* top:0%;
transform: translateY(-50%); */
}
I modified the original css To show where the Horizontal scroll Can end up showing, ex:
#horizontalcontainer {
/*
height: 100%; //show at the bottom
*/
height: 400px; //show after 400px
}
but you can change it to the taste of your project. You can use Jquery and Simplebar from CDN or move the CSS + JS files it to your project, to customize The scroll bar you need to Download simplebar.css and / or overwrite the css properties of simplebar.css with your own customizations.
Upvotes: 2
Reputation: 10237
You can use css-variable
to set value for the ::-webkit-scrollbar
and based on mouse movement, change the variable value and track it using setInterval
to hide the scrollbar after 2 seconds.
NOTE: For some strange reason, this does not work when clicking run snippet, user the full view and it will work. Guess with iframe or something.
let div = document.getElementById('scrolling-wrapper');
var myTimer = setInterval(onTimer, 2000);
window.addEventListener('mousemove', () => {
showScroll();
resetTimer();
});
function onTimer() {
hideScroll();
}
function resetTimer() {
clearInterval(myTimer);
myTimer = setInterval(onTimer, 2000);
}
function showScroll() {
div.style.setProperty('--scroll-display', 'block');
}
function hideScroll() {
div.style.setProperty('--scroll-display', 'none');
}
::-webkit-scrollbar {
height: 1%;
display: var(--scroll-display);
}
:root {
--scroll-display: none;
}
#scrolling-wrapper:hover> ::-webkit-scrollbar {
display: block;
}
/* Track */
::-webkit-scrollbar-track {
background: transparent;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: black;
border-radius: 25px;
}
#horizontalcontainer {
z-index: 0;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
}
#scrolling-wrapper {
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
text-align: center;
margin: 0 auto;
height: calc(100% - 145px);
width: 100vw;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: none;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.videocard1 {
padding-left: 27%;
padding-right: 2.5%;
display: inline-block;
position: relative;
width: 46.5%;
top: 50%;
transform: translateY(-50%);
}
.videocard {
padding-right: 2.5%;
display: inline-block;
position: relative;
width: 46.5%;
top: 50%;
transform: translateY(-50%);
}
.videocardlast {
padding-right: 27%;
display: inline-block;
position: relative;
width: 46.5%;
top: 50%;
transform: translateY(-50%);
}
<div id="horizontalcontainer">
<div id="scrolling-wrapper">
<div class="videocard1">
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://www.youtube.com/embed/_OBlgSz8sSM" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
<div class="videocard">
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://www.youtube.com/embed/_OBlgSz8sSM" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
<div class="videocardlast">
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://www.youtube.com/embed/_OBlgSz8sSM" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
</div>
</div>
Upvotes: 1