Related
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>
The site has several sections. The first one with a picture, on it header should be transparent. The following blocks are colored and on them the header must take the color of the block. How can I achieve this?
I wrote code to change the header from transparent to the color of the second block, but I think there is a better solution than writing this for each block, but I can't find it.
$(function() {
let header = $('.header'),
intro = $('.intro');
$(window).scroll(function() {
if ($(this).scrollTop() > intro.outerHeight()) {
header.addClass('header_filled');
} else {
header.removeClass('header_filled');
}
});
});
*,
*::before,
*::after {
box-sizing: border-box;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
}
a {
text-decoration: none;
}
body {
margin: 0;
font-family: 'Montserrat', sans-serif;
font-size: 15px;
line-height: 1.6;
color: #fff;
}
/* Animations */
/* Container */
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
}
/* Header */
.header {
width: 100%;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
}
.header__logo {
font-size: 30px;
font-weight: 700;
color: #fff;
}
.header__inner {
display: flex;
justify-content: space-between;
align-items: center;
}
.header_filled {
background-color: #3ebb46;
border-radius: 0 0 20px 20px;
transition: .2s ease-in;
}
/* Intro */
.intro {
display: flex;
flex-direction: column;
justify-content: center;
width: 100%;
height: 100vh;
background: url("../img/intro.jpg") center no-repeat;
background-size: cover;
font-size: 20px;
}
.intro__inner {
margin: 0 auto;
backdrop-filter: blur(2px);
-webkit-backdrop-filter: blur(2px);
border: 1px solid #fff;
border-radius: 30px;
}
.intro__title {
font-size: 72px;
text-align: center;
}
.intro__subtitle {
font-family: 'Jost', sans-serif;
text-transform: uppercase;
font-size: 36px;
text-align: center;
}
/* Navigation */
.nav {
display: flex;
font-size: 15px;
font-weight: 500;
text-transform: uppercase;
}
.nav__link {
color: #fff;
padding: 0 10px;
}
.nav__link:hover {
color: #ffffff;
background-color: #0d7711;
border-radius: 10px;
}
/* About */
.about {
background-color: #3ebb46;
width: 100%;
height: 100vh;
padding: 60px 0;
color: #fff;
font-size: 20px;
}
.about__title {
background-color: #61c467;
text-align: center;
border-radius: 10px;
}
.about__text {
text-align: justify;
}
.about__link {
font-size: 21px;
font-weight: 700;
color: #6868d8;
text-decoration: wavy;
padding: 0 2px 0 2px;
}
.about__link:hover {
text-decoration: none;
color: #3ebb46;
background-color: #fff;
border-radius: 5px;
transition: .1s ease-in;
}
/* Servives */
.services {
background-color: #48daae;
width: 100%;
height: 100vh;
padding: 60px 0;
color: #fff;
font-size: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght#400;500;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Jost&display=swap" rel="stylesheet">
<header class="header" id="header">
<div class="container">
<div class="header__inner" id="header">
<a href="#main">
<div class="header__logo">CottageKarelia</div>
</a>
<nav class="nav">
<a class="nav__link" href="#main">Главная</a>
<a class="nav__link" href="#about">О компании</a>
<a class="nav__link" href="#services">Услуги</a>
<a class="nav__link" href="#">Отдых в Карелии</a>
<a class="nav__link" href="#">Владельцам</a>
<a class="nav__link" href="#">Оплата</a>
<a class="nav__link" href="#">Контакты</a>
</nav>
</div>
</div>
</header>
<div class="intro" id="main">
<div class="container">
<div class="intro__inner">
<h1 class="intro__title">Гостевые дома и коттеджи Карелии</h1>
<br>
<h2 class="intro__subtitle">Простой выбор для Вашего отдыха!</h2>
</div>
</div>
</div>
<section class="about" id="about">
<div class="container">
<div class="about__title">
<h1>О деятельности компании</h1>
</div>
<div class="about__text">
<p>
Наш сайт является крупнейшим <a class="about__link" href="catalog.html">каталогом</a> гостевых домов и коттеджей в Карелии, на котором собрано более 1000 позиций. Здесь Вы сможете найти любой дом, соответствующий всем Вашим потребностям. Благодаря
удобной форме поиска, Вы наиболее полно сможете охарактеризовать, что именно Вам необходимо, после чего, Вам будут представлены наиболее подходящие дома. Когда Вы определитесь с выбором дома, Вам будет предложено забронировать его, после чего
и начнется Ваш отдых! Кроме того, мы с радостью предлагаем гостям Карелии различные туры, созданные для абсолютно любой категории людей.
</p>
<p>
Наши менеджеры свяжутся с Вами и узнают все Ваши пожелания, после чего они сформируют Вам тур: определят наиболее предпочтительные и удобные варианты проезда, сообщат о дополнительных возможностях на территории выбранного места или тура, посоветуют достопримечательности
Карелии, которые можно будет посетить неподалеку от выбранного дома, предложат Вам трансфер с вокзала к гостевому дому или коттеджу и обратно. Иными словами, за Вас сделают все и обеспечат Вам лучший отдых на земле в райском уголке, по имени Карелия!
</p>
</div>
</div>
</section>
<section class="services" id="services">
<div class="container">
<div class="services__title">
<h1>Дополнительные услуги</h1>
</div>
</div>
</section>
In order to determine wether the header block is above any of your blocks that change its color, you need to check if the header position + height "touches" the top edge of the element. After that you can simply apply the background color of the "touched" element to your header.
$(window).scroll(function(){
var $header = $(".header");
var header_position = $header.offset().top;
var header_height = $header.outerHeight();
$('.header-color').each(function(){
var color_block_position = $(this).offset().top;
if (header_position + header_height >= color_block_position) {
$header.css({
'background-color': $(this).css('background-color')
});
}
});
});
.header {
background-color: #CECECE;
font-size: 2em;
padding: 1em;
width: 100%;
position: fixed;
top: 0;
left: 0;
border: 1px solid red;
}
.header-color {
padding: 1em;
border: 1px solid red;
}
.transparent-background {
background-color: transparent;
}
.yellowgreen-background {
background-color: yellowgreen;
}
.orangered-background {
background-color: orangered;
}
.blue-background {
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="header">
HEADER
</div>
<br><br><br><br><br><br><br>
<div class="header-color transparent-background">
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 class="header-color yellowgreen-background">
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 class="header-color orangered-background" >
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 class="header-color blue-background">
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>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
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>
This is my code:
$(".left-area").mouseenter(function() {
$(".left-area-content").show();
$(".left-area-content-preview").hide();
}).mouseleave(function() {
$(".left-area-content").hide();
$(".left-area-content-preview").show();
});
$(".right-area").mouseenter(function() {
$(".right-area-content").show();
$(".right-area-content-preview").hide();
}).mouseleave(function() {
$(".right-area-content").hide();
$(".right-area-content-preview").show();
});
* {
font-size: 30px;
font-family: Arial;
}
body {
margin: 0;
padding: 0;
height: 100vh;
width: 100vw;
overflow: hidden;
}
.content {
display: flex;
height: 100vh;
overflow-y: scroll;
}
.left-area {
background-color: red;
color: white;
}
.left-area-content-preview {
display: block;
}
.left-area-content {
display: none;
width: 500px;
}
.main-area {
width: 100%;
}
.right-area {
background-color: red;
color: white;
}
.right-area-content {
width: 500px;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<div class="left-area">
<div class="left-area-content-preview">
One
</div>
<div class="left-area-content">
Some cool content
</div>
</div>
<div class="main-area">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 class="right-area">
<div class="right-area-content-preview">
Two
</div>
<div class="right-area-content">
Some cool content
</div>
</div>
</div>
I would need something like this:
http://www.laurelhalo.com/
The main area should keep its width while hovering one of the two sidebars, and push off on one side. There also should be a sliding animation, like in the example.
How is it possible to realize that? Is it possible with jQuery?
Would be very thankful for help. :)
Just add min-width:100%; to your main-area class.
$(".left-area").mouseenter(function() {
$(".left-area-content").show();
$(".left-area-content-preview").hide();
}).mouseleave(function() {
$(".left-area-content").hide();
$(".left-area-content-preview").show();
});
$(".right-area").mouseenter(function() {
$(".right-area-content").show();
$(".right-area-content-preview").hide();
}).mouseleave(function() {
$(".right-area-content").hide();
$(".right-area-content-preview").show();
});
* {
font-size: 30px;
font-family: Arial;
}
body {
margin: 0;
padding: 0;
height: 100vh;
width: 100vw;
overflow: hidden;
}
.content {
display: flex;
height: 100vh;
overflow-y: scroll;
}
.left-area {
background-color: red;
color: white;
}
.left-area-content-preview {
display: block;
}
.left-area-content {
display: none;
width: 500px;
}
.main-area {
width: 100%;
min-width:100%;
}
.right-area {
background-color: red;
color: white;
}
.right-area-content {
width: 500px;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<div class="left-area">
<div class="left-area-content-preview">
One
</div>
<div class="left-area-content">
Some cool content
</div>
</div>
<div class="main-area">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 class="right-area">
<div class="right-area-content-preview">
Two
</div>
<div class="right-area-content">
Some cool content
</div>
</div>
</div>
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>