I've made hamburger menu with sidebar list for mobile with some js. This is code:
<button class="hamburger">
<span class="hamburger__box">
<span class="hamburger__inner"></span>
</span>
</button>
<div class="navigation">
<ul class="navigation__list">
<li class="navigation__item">O mnie</li>
<li class="navigation__item">Oferta</li>
<li class="navigation__item">Technologie</li>
<li class="navigation__item 7" >Kontakt</li>
</ul>
</div>
There is js:
<script>
const hamburger = document.querySelector('.hamburger');
const nav = document.querySelector('.navigation');
const handleClick = () => {
hamburger.classList.toggle('hamburger--active');
nav.classList.toggle('navigation--active');
}
hamburger.addEventListener('click', handleClick);
</script>
And css (part of):
.hamburger
{
width:100%;
height: 72px;
margin-right: auto;
display: inline-block;
cursor: pointer;
background-color: transparent;
border:0;
}
.hamburger, .navigation
{
transition: transform .3s .1s ease-in-out;
}
.hamburger--active
{
transform: translateX(-120px);
}
.hamburger__box
{
width:100px;
height: 24px;
display: inline-block;
position:relative;
}
.hamburger__inner
{
width: 100%;
height: 10px;
background-color: #ff7300;
position:absolute;
left:0;
top:50%;
transform: translateY(-50%);
transition: background-color.1s .2s ease-in-out;
}
.hamburger__inner::before
{
content:'';
width: 100%;
height: 10px;
background-color: #000;
position:absolute;
left:0;
top:-20px;
transition: transform.2s .2s ease-in-out;
}
.hamburger__inner::after
{
content:'';
width: 100%;
height: 10px;
background-color: #000;
position:absolute;
left:0;
top:20px;
transition: transform.2s .2s ease-in-out;
}
.navigation
{
height:45vh;
font-size:25px;
width:200px;
background-color: #ff7300;
opacity: 0.9;
position: absolute;
top:0;
right:0;
transform: translateX(200px);
font-family: 'Raleway', sans-serif;
font-weight: 900;
}
.navigation--active
{
transform: translateX(0px);
}
.navigation__item
{
margin-top: 30px;
list-style: none;
}
.navigation__item
{
margin-bottom: 10px;
color:#fff;
a
{
text-decoration: none;
color: #000;
}
}
Idea is simple to move sidebar menu out of screen but then horizontal scroll is showing, I only test this in device mode in Firefox so i don't know how it will looks like on my phone (but i suppose the scroll doesn't disapear in magic way). I've also tried with display:none; for inactive list but this command doesn't support animation. It's possible to fix this idea or it is just wrong by design?
You can Use The overflow Property
overflow-x:hidden;
This is to remove scroll horizontally at it to the body style sheet.
I recommend to use a sidebar with position: fixed, especially for mobile views.
So the position of the sidebar is not affected by the bodys scroll position:
The animation to show/hide the sidebar can be done with left property or transform: translateX. Here is an example. Note that I saved the width of the sidebar using a root variable.
let burgerMenu = document.getElementById('burger-menu');
let sidebar = document.getElementById('sidebar');
burgerMenu.addEventListener('click', () => {
sidebar.classList.toggle('sidebar__active');
});
:root{
--sidebar-width: 120px;
}
body{
magin: 0;
padding: 0;
background: #dedede;
}
.sidebar{
position: fixed;
top: 0;
left: calc(-1 * var(--sidebar-width));
width: var(--sidebar-width);
height: 100vh;
overflow-y: auto;
background: #fff;
border-right: 1px solid black;
transition: left 1s linear;
z-index: 2;
}
.sidebar.sidebar__active{
left: 0px;
}
.burger-menu{
position: fixed;
top: 0;
right: 0;
z-index: 1;
height: 72px;
font-size:36px;
}
.content{
position: relative;
width: 100%;
box-sizing: border-box;
padding-top: 24px;
padding-bottom: 24px;
padding-right: 64px;
padding-left: 64px;
background: #fff;
color: #000;
font-size: 24px;
}
<nav id="sidebar" class="sidebar">
Sidebar
</nav>
<button id="burger-menu" class="burger-menu">Toggle sidebar</button>
<section class="content">
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet</p>
</section>
Related
I'm stuck at my one-pager navigation logic. As you can see in my detailed example below, I already have a dynamic navigation depending on the scroll position. Also, when you click a navigation item, you are getting scrolled down to the specific section.
What I'm stuck at is the point to add/remove the active class to the navigation item. Somehow, I can't find a logic in my brain to make this a smart part of my navigation. I know that I can make some static JS code, but that's not what I want.
At least, I just want to add another menu item and an element containing the data-waypoint attribute.
It's not an option to add this to the item click functionality, since the user can scroll down manually, which then don't get recognized!
(function($) {
$(document).ready(function() {
let nav = $('#nav');
let navOffsetTop = nav.offset().top;
$(window).scroll(function() {
if ($(this).scrollTop() >= navOffsetTop) {
nav.addClass('sticky');
} else {
nav.removeClass('sticky');
}
// Somehow add logic here for changing active classes...
if ($(this).scrollTop() >= $('#content').offset().top) {
//console.log('Reached');
}
});
$('.nav-item').click(function() {
let navPosition = nav.css('position');
let navOuterHeight = nav.outerHeight();
let scrollTo = $(this).data('scroll-to');
let scrollTop = $(`[data-waypoint=${scrollTo}]`).offset().top - navOuterHeight - 15;
if (navPosition === 'static') {
scrollTop = scrollTop - navOuterHeight - 30;
}
$([document.documentElement, document.body]).animate({
scrollTop: scrollTop
}, 500);
});
});
})(jQuery);
#page {
width: 100%;
padding-left: 50px;
padding-right: 50px;
box-sizing: border-box;
border: 1px solid;
}
#container {
width: 100%;
height: 1500px;
}
#nav {
width: 100%;
background-color: #aaa;
margin-bottom: 30px;
z-index: 1;
display: flex;
justify-content: space-between;
}
#nav .nav-item {
padding: 20px;
display: flex;
justify-content: center;
flex: 1;
cursor: pointer;
}
#nav .nav-item.active {
color: #fff;
}
#nav.sticky {
position: fixed;
top: 0;
left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="page">
<h1>Lorem Impsum page</h1>
<div id="nav">
<div class="nav-item active" data-scroll-to="home">Home</div>
<div class="nav-item" data-scroll-to="content">Content</div>
<div class="nav-item" data-scroll-to="about">About</div>
</div>
<div id="container">
<div id="home" data-waypoint="home">
<h2>Home</h2>
<div class="inner">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
</div>
<div id="content" data-waypoint="content">
<h2>Content</h2>
<div class="inner">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
</div>
<div id="about" data-waypoint="about">
<h2>About</h2>
<div class="inner">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
</div>
</div>
</div>
I'm happy to share my answer I've found. I was first looking for a simple solution, but ended up using Waypoints jQuery library.
This is my solution. I hope it helps someone:
(function($) {
$(document).ready(function() {
let nav = $('#nav');
let navOffsetTop = nav.offset().top;
let navItem = $('.nav-item', nav);
$(window).on('resize, scroll', function() {
initNav(nav, navOffsetTop);
initWaypoints(nav, navItem);
});
$(window).resize(function() {
setNavHeight(nav);
});
navItem.click(function() {
let navOuterHeight = nav.outerHeight();
let scrollTo = $(this).data('scroll-to');
let scrollTop = $(`[data-waypoint=${scrollTo}]`).offset().top - navOuterHeight - 10;
$([document.documentElement, document.body]).animate({
scrollTop: scrollTop
}, 500);
});
setNavHeight(nav);
initNav(nav);
});
function setNavHeight(nav) {
let navItems = $('#nav-items', nav);
nav.css('min-height', `${navItems.outerHeight()}px`);
}
function initNav(nav, navOffsetTop) {
let navItems = $('#nav-items', nav);
let windowScrollTop = $(window).scrollTop();
if (windowScrollTop >= navOffsetTop) {
navItems.addClass('sticky');
} else {
navItems.removeClass('sticky');
}
}
function initWaypoints(nav, navItem) {
$('.block-waypoint').waypoint(function() {
let waypoint = $(this.element).data('waypoint');
let navItemWaypoint = $(`.nav-item[data-scroll-to=${waypoint}]`, nav);
navItem.removeClass('is-active');
if (navItemWaypoint.length) {
navItemWaypoint.addClass('is-active');
}
}, {
offset: 69
});
}
})(jQuery);
#page {
width: 100%;
padding-left: 50px;
padding-right: 50px;
box-sizing: border-box;
border: 1px solid;
}
#container {
width: 100%;
height: 1500px;
}
#nav {
margin-bottom: 30px;
}
#nav-items {
width: 100%;
background-color: #aaa;
margin-bottom: 30px;
z-index: 1;
display: flex;
justify-content: space-between;
}
#nav-items.sticky {
position: fixed;
top: 0;
left: 0;
}
.nav-item {
padding: 20px;
display: flex;
justify-content: center;
flex: 1;
cursor: pointer;
}
.nav-item.is-active {
color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/jquery.waypoints.min.js"></script>
<div id="page">
<h1>Lorem Impsum page</h1>
<div id="nav">
<div id="nav-items">
<div class="nav-item is-active" data-scroll-to="home">Home</div>
<div class="nav-item" data-scroll-to="content">Content</div>
<div class="nav-item" data-scroll-to="about">About</div>
</div>
</div>
<div id="container">
<div id="home" class="block-waypoint" data-waypoint="home">
<h2>Home</h2>
<div class="inner">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
</div>
<div id="content" class="block-waypoint" data-waypoint="content">
<h2>Content</h2>
<div class="inner">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
</div>
<div id="about" class="block-waypoint" data-waypoint="about">
<h2>About</h2>
<div class="inner">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
</div>
</div>
</div>
Also, I've wrapped the nav items into a wrapper and set the margin to the outer nav. During page init and resize, I'm setting a min-width to the outer nav to prevent any content jumping and issues with the waypoints. Otherwise, the offset and all the other calculation stuff makes a lot of problems.
I would need the following:
On button click, the red circle should center in the middle of the
text box.
It should be based on the pixel position of the screen. (No nesting
with flexbox or something like that.)
It should work responsive.
Here is my approach:
$("button").click(function() {
$("#circle").css("left", middle_point_of_box);
$("#circle").css("right", middle_point_of_box);
});
#text {
background-color: lightgray;
width: 40%;
}
#circle {
width: 20vw;
height: 20vw;
background-color: red;
border-radius: 50%;
position: absolute;
top: 0; /* Middle Point of Text Box */
left: 0; /* Middle Point of Text Box */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="text">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
<div id="circle"></div>
<button>Click me</button>
How is it possible to code that? I would be very thankful for help!
Just use a combination of jQuery's offset() and width()
let targetCenter = {
x: $('#text').offset().left + $('#text').width() / 2 - $('#circle').width() / 2,
y: $('#text').offset().top + $('#text').height() / 2 - $('#circle').height() / 2
}
$("button").click(function(e) {
$("#circle").css("left", targetCenter.x + 'px');
$("#circle").css("top", targetCenter.y + 'px');
});
#text {
background-color: lightgray;
width: 40%;
}
#circle {
width: 20vw;
height: 20vw;
background-color: red;
border-radius: 50%;
position: absolute;
top: 0;
/* Middle Point of Text Box */
left: 0;
/* Middle Point of Text Box */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="text">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
<div id="circle"></div>
<button>Click me</button>
I am tying to implement a Draggable overlay screen(initially positioned at the bottom half) that passes through another screen. An example of how I would like it to look is as described here - https://medium.com/#iamWaseem99/how-to-make-swipable-draggable-overlay-views-in-swift-xcode-82a86adece9c.
Disclosure regarding the tools currently being used - TailwindCSS for styling, HTML, CSS and JS via the Stimulus JS framework.
Current approach - I have installed Hammer JS and was attempting to achieve this by tracking the "panup" event and adjust the height of both the divs to seem as through the bottom screen was passing through. This ended up being messy, was wondering if there is a cleaner approach to achieve this.
I have found a React library - https://github.com/manufont/react-swipeable-bottom-sheet, however I am currently not using the React framework so was wondering if there are any alternatives through which this can be achieved.
Thank you!
Based on the two links in your question i made a solution with Hammer.js but with "swipe" and top instead of "panup" and height. I don't know what is messy for you, but this is imo very clean:
hammerOverlay.on('swipe', (e) => {
overlay.style.top = ( e.deltaY < 0 ) ? 0 : (window.innerHeight - triggerHeight) + 'px';
});
Working example:
const overlay = document.querySelector('#overlay');
const triggerHeight = document.querySelector('#trigger').clientHeight;
const hammerOverlay = new Hammer(overlay);
hammerOverlay.get('swipe').set({ direction: Hammer.DIRECTION_VERTICAL });
hammerOverlay.on('swipe', (e) => {
overlay.style.top = ( e.deltaY < 0 ) ? 0 : (window.innerHeight - triggerHeight) + 'px';
});
#wrapper {
position: relative;
}
#overlay {
position: fixed;
top: calc(100% - 50px);
background-color: #ddd;
transition: top 300ms;
}
#trigger h3 {
height: 50px;
margin: 0;
text-align: center;
background-color: #eee;
}
<script src="https://hammerjs.github.io/dist/hammer.js"></script>
<div id="wrapper">
<div id="overlay">
<div id="trigger"><h3>Swipeable bottom sheet</h3></div>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
</div>
</div>
If you want an arrow like that in your first link, here is a solution with css arrows:
const overlay2 = document.querySelector('#overlay2');
const triggerHeight2 = document.querySelector('#trigger2').clientHeight;
const hammerOverlay2 = new Hammer(overlay2);
hammerOverlay2.get('swipe').set({ direction: Hammer.DIRECTION_VERTICAL });
hammerOverlay2.on('swipe', (e) => {
if( e.deltaY < 0 ) {
overlay2.style.top = 0;
overlay2.querySelector('.arrow').classList.remove('up');
overlay2.querySelector('.arrow').classList.add('down');
}
else {
overlay2.style.top = (window.innerHeight - triggerHeight2) + 'px';
overlay2.querySelector('.arrow').classList.remove('down');
overlay2.querySelector('.arrow').classList.add('up');
}
});
#wrapper {
position: relative;
}
#overlay2 {
position: fixed;
top: calc(100% - 50px);
background-color: #ddd;
transition: top 300ms;
}
#trigger2 {
display: flex;
justify-content: center;
align-items: center;
height: 50px;
background-color: #eee;
}
.arrow {
display: inline-block;
padding: 3px;
border: solid black;
border-width: 0 3px 3px 0;
}
.up {
transform: rotate(-135deg);
-webkit-transform: rotate(-135deg);
}
.down {
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
<script src="https://hammerjs.github.io/dist/hammer.js"></script>
<div id="wrapper">
<div id="overlay2">
<div id="trigger2"><i class="arrow up"></i></div>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
</div>
</div>
My Goal
I want to use a good-looking scrollbar that i found on this website Bootstrap Scrollbar.
My Problem
However i am struggeling with the logic behind it.
Since a scrollbar is added automatically, where in the HTML do i have to locate the bootstrap-scrollbar-div ?
If I have for example 2 separate div-containers and I want in each of them to follow a certain scrollbar-color, how do i achieve it ?
Do i have to warp my 2 div-containers each within the bootstrap-scrollbar ?
Note:
If anything is unclear or if I formulated my question to unprecisely, leave a comment.
In the following code, the bootstrap is not working, this is the reason why i am asking this question.
The Code-Snipped
.scrollbar-morpheus-den::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1);
background-color: #F5F5F5;
border-radius: 10px;
}
.scrollbar-morpheus-den::-webkit-scrollbar {
width: 12px;
background-color: #F5F5F5;
}
.scrollbar-morpheus-den::-webkit-scrollbar-thumb {
border-radius: 10px;
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1);
background-image: -webkit-gradient(linear, left bottom, left top, from(#30cfd0), to(#330867));
background-image: -webkit-linear-gradient(bottom, #30cfd0 0%, #330867 100%);
background-image: linear-gradient(to top, #30cfd0 0%, #330867 100%);
}
.scrollbar-morpheus-den {
scrollbar-color: #330867 #F5F5F5;
}
<!doctype html>
<html lang="de">
<head>
</head>
<body>
<div class="scrollbar scrollbar-lady-lips">
<div class="force-overflow"></div>
</div>
<div class="test2">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos
et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna
aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur
sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
sit amet.Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
</div>
</body>
</html>
What if add class scrollbar-morpheus-den to <div> tag?
e.g. <div class="test2 scrollbar-morpheus-den">
I have added the height: 100px; and overflow: auto; to class .test so that overflow happens with the content available.
.scrollbar-morpheus-den::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1);
background-color: #F5F5F5;
border-radius: 10px;
}
.scrollbar-morpheus-den::-webkit-scrollbar {
width: 12px;
background-color: #F5F5F5;
}
.scrollbar-morpheus-den::-webkit-scrollbar-thumb {
border-radius: 10px;
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1);
background-image: -webkit-gradient(linear, left bottom, left top, from(#30cfd0), to(#330867));
background-image: -webkit-linear-gradient(bottom, #30cfd0 0%, #330867 100%);
background-image: linear-gradient(to top, #30cfd0 0%, #330867 100%);
}
.scrollbar-morpheus-den {
scrollbar-color: #330867 #F5F5F5;
}
.test2 {
height: 100px;
overflow: auto;
}
<!doctype html>
<html lang="de">
<head>
</head>
<body>
<div class="scrollbar scrollbar-lady-lips">
<div class="force-overflow"></div>
</div>
<div class="test2 scrollbar-morpheus-den">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos
et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna
aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur
sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
sit amet.Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
</div>
</body>
</html>
I want to implement a custom scrollbar with a flexible track that expands around the thumb using CSS. I try to achieve something like a gravitational lens effect, as if the thumb (red dot) warps the space around it (see the picture below). The gravitational lens shall move with the thumb.
How can I do that?
First: It's possible to build the scrollbar just with HTML and CSS but for the usage you need Javascript.
Simple scrollbar
You can achieve the look with position, border and border-radius. The track gets the border on the left and the right side, the thumb gets it on all sides with a border-radius: 50% and additionally a white mask (with the width of the track minus its borders) for hiding the thumb borders inside the track. Of course you need also the red dot. All five elements get a position: absolute.
<div id="scrollbar">
<div id="track"></div>
<div id="thumb">
<div class="white_mask"></div>
<div id="red_dot"></div>
</div>
</div>
Basic CSS (without dimensions)
#scrollbar {
position: absolute;
}
#track {
position: absolute;
border-right: 3px solid #000;
border-left: 3px solid #000;
}
#thumb {
position: absolute;
border: 1px solid #000;
border-radius: 50%;
background-color: white;
}
.white_mask {
position: absolute;
background-color: white;
}
#red_dot {
position: absolute;
border-radius: 50%;
background-color: #9c0000;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
}
#scrollbar {
position: absolute;
right: 100px;
top: 0;
width: 120px;
height: 100%;
z-index: 10;
}
#track {
position: absolute;
top: 0;
right: 20px;
width: 80px;
height: 100%;
border-right: 12px solid #000;
border-left: 12px solid #000;
}
#thumb {
position: absolute;
top: 0;
right: 0;
width: 120px;
height: 128px;
border: 4px solid #000;
border-top: 8px solid #000;
border-bottom: 8px solid #000;
border-radius: 50%;
background-color: white;
}
.white_mask {
position: absolute;
top: -8px;
right: 28px;
width: 56px;
height: 128px;
background-color: white;
}
.white_mask.big {
top: -16px;
right: 12px;
width: 88px;
height: 144px;
}
#thumb_mask {
position: absolute;
top: -16px;
left: 8px;
width: 96px;
height: 144px;
overflow: hidden;
}
.quarter_border {
position: absolute;
width: 80px;
height: 100px;
border-right: 12px solid #000;
border-left: 12px solid #000;
border-radius: 50%;
background-color: white;
}
.quarter_border.top {
top: -52px;
}
.quarter_border.right {
right: -60px;
}
.quarter_border.bottom {
bottom: -52px;
}
.quarter_border.left {
left: -60px;
}
#red_dot {
position: absolute;
top: 0;
left: 0;
width: 112px;
height: 112px;
border: 8px solid white;
border-radius: 50%;
background-color: #9c0000;
}
<div id="container">
<div id="scrollbar">
<div id="track"></div>
<div id="thumb">
<div class="white_mask"></div>
<div id="red_dot"></div>
</div>
</div>
</div>
Advanced scrollbar
Since there are small corners where thumb and track meet each other you can add four additional divs with rounded borders in a masking div with overflow: hidden so that just a quarter of the four divs is visible. You need also a second white mask under the four divs to hide the corners.
For increasing and decreasing the border-width you need to define different values for top/bottom border and left/right border. Furthermore the red dot needs a white border for smoothing the inside of the thumb border.
<div id="scrollbar">
<div id="track"></div>
<div id="thumb">
<div class="white_mask"></div>
<div class="white_mask small"></div>
<div id="thumb_mask">
<div class="quarter_border top right"></div>
<div class="quarter_border bottom right"></div>
<div class="quarter_border top left"></div>
<div class="quarter_border bottom left"></div>
</div>
<div id="red_dot"></div>
</div>
</div>
Additional CSS (without dimensions)
#thumb {
...
border-top: 2px solid #000;
border-bottom: 2px solid #000;
}
#thumb_mask {
position: absolute;
overflow: hidden;
}
.quarter_border {
position: absolute;
border-right: 3px solid #000;
border-left: 3px solid #000;
border-radius: 50%;
background-color: white;
}
#red_dot{
...
border: 2px solid white;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
}
#scrollbar {
position: absolute;
right: 100px;
top: 0;
width: 120px;
height: 100%;
z-index: 10;
}
#track {
position: absolute;
top: 0;
right: 20px;
width: 80px;
height: 100%;
border-right: 12px solid #000;
border-left: 12px solid #000;
}
#thumb {
position: absolute;
top: 0;
right: 0;
width: 120px;
height: 128px;
border: 4px solid #000;
border-top: 8px solid #000;
border-bottom: 8px solid #000;
border-radius: 50%;
background-color: white;
}
.white_mask {
position: absolute;
top: -4px;
right: 28px;
width: 56px;
height: 128px;
background-color: white;
}
.white_mask.big {
top: -16px;
right: 12px;
width: 88px;
height: 144px;
}
#thumb_mask {
position: absolute;
top: -16px;
left: 8px;
width: 96px;
height: 144px;
overflow: hidden;
}
.quarter_border {
position: absolute;
width: 80px;
height: 100px;
border-right: 12px solid #000;
border-left: 12px solid #000;
border-radius: 50%;
background-color: white;
}
.quarter_border.top {
top: -52px;
}
.quarter_border.right {
right: -60px;
}
.quarter_border.bottom {
bottom: -52px;
}
.quarter_border.left {
left: -60px;
}
#red_dot {
position: absolute;
top: 0;
left: 0;
width: 112px;
height: 112px;
border: 8px solid white;
border-radius: 50%;
background-color: #9c0000;
}
<div id="container">
<div id="scrollbar">
<div id="track"></div>
<div id="thumb">
<div class="white_mask"></div>
<div class="white_mask big"></div>
<div id="thumb_mask">
<div class="quarter_border top right"></div>
<div class="quarter_border bottom right"></div>
<div class="quarter_border top left"></div>
<div class="quarter_border bottom left"></div>
</div>
<div id="red_dot"></div>
</div>
</div>
</div>
Unfortunately the quarters don't fit perfectly to thumb and track. So it could be a better approach to build the scrollbar as SVG and manipulate its components instead.
Basic Javascript
There are many possibilities and features to manipulate the scrollbar with different properties like top, scrollTop or transform. I use here for demonstration only top and some basic features (for example I omitted the adjustment of the scrollposition on resize).
Basic constants
For getting the scrollbar to work first you need three constants thumb_height (incl. its borders), scroll_range (maximum thumb position) and diff_height (hidden content).
const thumb_height = thumb.getBoundingClientRect().height;
const scroll_range = window.innerHeight - thumb_height;
const diff_height = content.scrollHeight - window.innerHeight
Scroll function
Then you need the scroll function where you calculate the new thumb position and the content scroll and style both elements if the thumb is in the scroll range.
The content scroll is the visible percentage of the initial hidden content. The percentage is calculated with: thumb position divided by its maximum, the scroll range.
For dragging the thumb:
You get the thumb position from the mouse cursor position in the mousedown event: e.clientY (corrected by the half of the thumb height).
You also have to make sure that the thumb doesn't disappear when the thumb position gets too small or too big, for example when leaving the container (here the window). Therefor you have to check if the position is lower than 0 or higher than the scroll range and style the elements only if not.
function dragThumb(e) {
const thumb_pos = e.clientY - (thumb_height / 2);
const content_scroll = -diff_height * thumb_pos / scroll_range;
if (thumb_pos >= 0 && thumb_pos <= scroll_range) {
thumb.style.top = thumb_pos + 'px';
content.style.top = content_scroll + 'px';
}
}
For mouse wheel:
You get the thumb position from the actual top property of the thumb increased or decreased (depending on the mouse wheel direction in the wheel event: e.deltaY) by the fixed amount 100 (you can modify the value to scroll faster or slower).
For the styling you additionally have to handle the two extreme conditions because the thump position (calculated with the fixed amount) sometimes doesn't "land" exactly on 0 or the scroll range. You could do this with if blocks like in dragThumb() (you would need 3) or you could use ternary operators ? : like in the following code snippet.
function scrollContent(e) {
const thumb_pos = parseInt(thumb.style.top) + (e.deltaY < 0 ? -100 : 100);
const content_scroll = -diff_height * thumb_pos / scroll_range;
thumb.style.top = thumb_pos < 0 ? 0 : (thumb_pos > scroll_range ? scroll_range : thumb_pos) + 'px';
content.style.top = thumb_pos < 0 ? 0 : (thumb_pos > scroll_range ? -diff_height : content_scroll) + 'px';
}
Event listener
Last you need an event listener where you call the scroll function.
For the mouse wheel:
document.addEventListener('wheel', scrollContent);
For dragging the thumb:
You need two additional event listeners, one for listening for the mouse move only if the thumb is initially clicked, and one for removing that mouse move listener if the mouse button is released.
thumb.addEventListener('mousedown', function(e) {
e.preventDefault(); // fixed a bug with 'mouseup'
document.addEventListener('mousemove', dragThumb);
});
document.addEventListener('mouseup', function() {
document.removeEventListener('mousemove', dragThumb);
});
Working example:
Both scroll functions are merged into the function scrollContent(). The thumb position is calculated in the two event handlers (which call scrollContent()): dragThumb() and the anonymous function for the wheel event.
The three constants are calculated in a reset function resetScroll() (and therefor defined as ordinary vars with let) that is called on page load and window resize. That function also calles the scroll function scrollContent() with the actual thumb position.
Because the event listener for mouseup is "deaf" if the event happens outside the stack snippet, i converted its anonymous function in a function stopDrag() that is called as event handler for mouseup and mouseleave.
document.addEventListener('DOMContentLoaded', function() {
const thumb = document.getElementById('thumb');
const content = document.getElementById('content');
let thumb_height, scroll_range, diff_height;
function resetScroll() {
thumb_height = thumb.getBoundingClientRect().height;
scroll_range = window.innerHeight - thumb_height;
diff_height = content.scrollHeight - window.innerHeight;
scrollContent(parseInt(thumb.style.top));
}
function scrollContent(thumbPos) {
const newScroll = -diff_height * thumbPos / scroll_range;
thumb.style.top = thumbPos < 0 ? 0 : (thumbPos > scroll_range ? scroll_range : thumbPos) + 'px';
content.style.top = thumbPos < 0 ? 0 : (thumbPos > scroll_range ? -diff_height : newScroll) + 'px';
}
function dragThumb(e) {
scrollContent(e.clientY - (thumb_height / 2));
}
function stopDrag(e) {
document.removeEventListener('mousemove', dragThumb);
}
thumb.addEventListener('mousedown', function(e) {
e.preventDefault();
document.addEventListener('mousemove', dragThumb);
});
document.addEventListener('mouseup', stopDrag);
document.addEventListener("mouseleave", stopDrag);
document.addEventListener('wheel', function(e) {
if (!e.ctrlKey) {
scrollContent(parseInt(thumb.style.top) + (e.deltaY < 0 ? -100 : 100));
}
});
window.addEventListener('resize', resetScroll);
//initial reset
document.scrollTop = 0;
thumb.style.top = 0;
resetScroll();
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#container {
position: relative;
overflow: hidden;
}
#content {
position: relative;
top: 0;
right: 0;
width: 100vw;
height: 100vh;
padding-right: 40px;
}
#scrollbar {
position: absolute;
right: 5px;
top: 0;
width: 30px;
height: 100%;
z-index: 10;
}
#track {
position: absolute;
top: 0;
right: 5px;
width: 20px;
height: 100%;
border-right: 3px solid #000;
border-left: 3px solid #000;
}
#thumb {
position: absolute;
top: 0;
right: 0;
width: 30px;
height: 32px;
border: 1px solid #000;
border-top: 2px solid #000;
border-bottom: 2px solid #000;
border-radius: 50%;
background-color: white;
}
.white_mask {
position: absolute;
top: -3px;
right: 6px;
width: 14px;
height: 30px;
background-color: white;
}
.white_mask.big {
top: -4px;
right: 3px;
width: 22px;
height: 36px;
}
#thumb_mask {
position: absolute;
top: -4px;
left: 2px;
width: 24px;
height: 36px;
overflow: hidden;
}
.quarter_border {
position: absolute;
width: 20px;
height: 25px;
border-right: 3px solid #000;
border-left: 3px solid #000;
border-radius: 50%;
background-color: white;
}
.quarter_border.top {
top: -13px;
}
.quarter_border.right {
right: -15px;
}
.quarter_border.bottom {
bottom: -13px;
}
.quarter_border.left {
left: -15px;
}
#red_dot {
position: absolute;
top: 0;
left: 0;
width: 28px;
height: 28px;
border: 2px solid white;
border-radius: 50%;
background-color: #9c0000;
}
<div id="container">
<div id="scrollbar">
<div id="track"></div>
<div id="thumb">
<div class="white_mask"></div>
<div class="white_mask big"></div>
<div id="thumb_mask">
<div class="quarter_border top right"></div>
<div class="quarter_border bottom right"></div>
<div class="quarter_border top left"></div>
<div class="quarter_border bottom left"></div>
</div>
<div id="red_dot"></div>
</div>
</div>
<div id="content">
<p>first</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>last</p>
</div>
</div>