I have a small webapp with an <aside>
which is scrollable. As I don't like how scrollbars are rendered in Windows, even with some CSS hacks, I now just use this to hide them completely:
aside {
border-right: 1px solid #333333;
overflow-y: scroll;
scrollbar-width: none;
}
You can still scroll it with the mouswheel. What I want to display instead of the ugly scrollbar is a separate div at the bottom (if you can scroll down) and/or at the top (if you can scroll up) with a simple arrow. This should only be visible if you hover. Can this be done with CSS only or do I need some javascript to calculate if the aside
can be scrolled in either direction?
I have a small webapp with an <aside>
which is scrollable. As I don't like how scrollbars are rendered in Windows, even with some CSS hacks, I now just use this to hide them completely:
aside {
border-right: 1px solid #333333;
overflow-y: scroll;
scrollbar-width: none;
}
You can still scroll it with the mouswheel. What I want to display instead of the ugly scrollbar is a separate div at the bottom (if you can scroll down) and/or at the top (if you can scroll up) with a simple arrow. This should only be visible if you hover. Can this be done with CSS only or do I need some javascript to calculate if the aside
can be scrolled in either direction?
- 1 CSS can't "detect" overflow so JS would be required. – Paulie_D Commented yesterday
- 2 Frankly, though if you don't like the default scrollbars, replace them with custom ones. It's not that hard. – Paulie_D Commented yesterday
- Looks like it can be done in both webkit and non webkit browsers: onaircode.com/html-css-custom-scrollbar-examples – chrwahl Commented yesterday
1 Answer
Reset to default 0After @Paulie_D's comment I found an easy way to achieve what I had in mind with some CSS and JavaScript:
function debounce(cb, wait = 300) {
let timer = 0;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => cb(...args), wait);
};
}
const onScroll = debounce(
() => {
const aside = document.querySelector('aside');
document.querySelector('.scroll.up').style.display = (aside.scrollTop > 0) ? 'block' : 'none';
document.querySelector('.scroll.down').style.display = ((aside.scrollTop + aside.clientHeight) < aside.scrollHeight) ? 'block' : 'none';
},
100
);
document.addEventListener('DOMContentLoaded', () => document.querySelector('aside').addEventListener('scroll', onScroll));
body {
display: grid;
grid-template-rows: 1fr;
height: 100vh;
width: 100vw;
margin: 0;
}
main {
display: grid;
grid-template-columns: 200px 1fr;
overflow: hidden;
}
aside.left {
border-right: 1px solid #333333;
overflow-y: scroll;
scrollbar-width: none;
}
.large {
height: 1000px;
background: linear-gradient(#0000AA, #FF0000);
}
aside .scroll {
position: fixed;
left: 0;
width: 200px;
height: 30px;
background-color: #33333380;
text-align: center;
color: #FFFFFF;
}
aside .scroll.up {
top: 0;
}
aside .scroll.down {
bottom: 0;
}
<main>
<aside class="left">
<div class="large"></div>
<div class="scroll up" style="display: none">UP</div>
<div class="scroll down">DOWN</div>
</aside>
<div class="main"></div>
</main>
If you scroll on the gradient the UP and DOWN div are shown or hidden depending on how far you scrolled.