When a box doesn't have engough space to hold its content, it has a few choices, the most common ones are:
The CSS prop corresponding to those scenarios are:
overflow: visible;
overflow: hidden
or overflow: clip;
(hidden & clip both disables user scroll, but only hidden allows prgrammatic scroll which give developer a way to scroll using Javascript)overflow: scroll;
Sometimes, dimension of content could be dynamic, when content container has enough space, we do not wish to show a scrollbar, otherwise, display it. To do this, simply use overflow: auto
, this is probably the most used value.
PS: you can also specify overflow direction using overflow-x
and overflow-y
When tracking element scroll position, those props come in handy (suppose we are talking about vertical scrolling)
MDN provides good explainination for this
aside from these, the follwing props are also associated with scrolling:
you can search the prop in mdn for details, for instance, scrollTop gets or sets the number of pixels that an elements's content is scrolled vertically
we could use it to detect whether an element has scrolled to bottom:
function scrolledToBottom(box) {
const { scrollTop, offsetHeight, scrollHeight } = box;
return scrollTop + offsetHeight === scrollHeight;
}
This task on itself is quite simple, all we need to do is record last scroll position, and compare it with current scroll position:
let lastScrollTop = box.scrollTop;
box.addEventListener("scroll", function(){
if (box.scrollTop > lastScrollTop) console.log("scroll directon: down")
else console.log("scroll direction: up")
lastScrollTop = box.scrollTop
})
What if we want to detect scroll direction but prevent scrolling to happen?
Before I show you the solution, the suitable question could be "Why would anyone want to do that?"
Well, suppose you wrote a long article, any user could read the first few paragraphs, but you want user to login in order to read the full article. In this scenario, when user scrolls down, you would want prevent scrolling, at the same time, show a login modal.
How to prevent scrolling while scrolling? Simple, use preventDefault
, right?
Actually, there's a catch, the goal is to prevent scrolling only when scroll direction is downward, and how do we detect scroll direction: by comparing scrollTop prop which only changes after scrolling.
Seems like we need a way to detect scroll direction without actually triggering scroll.
The solution I come up with is to listen to whell
event to detect scroll direction. After all, page scroll is caused by scrolling mouse wheel (or trackpad which also dispathes wheel
event)
box.addEventListener("wheel", function(e) {
if (e.deltaY <= 0) return; // scroll up
e.preventDefault();
// below should be code to display the login modal
})
What is this deltaY
thing? It turns out to be a parameter associated with your mouse that indicates how much the mouse wheel(not the page) has scrolled vertically. It comes in handy for direction detection: the value is positive if scroll down, negative if scroll up.
Think of a scenario where a box and it's container are both scrollable.
If you scroll insdie the box, by default, when it hasn't scrolled to bottom, only the box will scroll, it's container won't. However, if you scrolled to the bottom and keep scrolling, it's container will start to scroll. This is called scroll-chain.
But sometimes, you don't want this default behavior, that is, when the box has scrolled to the bottom, do not scoll it's container when keep scrolling.
Well, we could set overscroll-behavior
to contain
to do this. (till 2021-08-24, safari still doesn't support this)
For details, see MDN overscroll-behavior
You may have noticed on different platforms, default scrollbar style differs. This inconsistency could harm UI experience.
Unfortunately, until today (2021-08-18), there isn't an unified standard on how to style scrollbars. Difference engines provide different CSS props to do this.
Fortunately, most browsers (chrome, safari, edge) uses webkit as its rendering engine (Firefox is a little special since it uses Gecko, other browsers have small market share). As UI developers, we need to write 2 set of rules, one for webkit and one for Gecko.
webkit users ::-webkit
as prefix, most of the time, we want to set scrollbar-track and scrollbar-thumb when doing customization, e.g.
.any-class::-webkit-scrollbar {
height: 10px; // use height if u are styling horizontal scrollbar
width: 10px; // use width if u are styling vertical scrollbar
}
.any-class::-webkit-scrollbar-track {
background: #F5F5F7;
}
.any-class::-webkit-scrollbar-thumb {
background: #C1C1C1;
border-radius: 5px;
}
Firefox's Gecko offers fewer but simpler css props for scrollbar styling, named scrollbar-width
and scrollbar-color
, e.g.
.any-class {
scrollbar-width: thin; // firefox uses keywords such as auto, thin, none
scrollbar-color: #C1C1C1 #F5F5F7; // thumb bgcolor & track bgcolor
}