I'm trying to make a custom scrollbar for my web app.
The mechanism for my scrollbar is the default scrollbar is shifted right by 100px padding and it is hidden by overflow:hidden of the parent container
$(".scrollbar-vertical").parent().children(".content").scroll(function(){
scrollerHeight = ( $(this).parent().height() / $(this).prop("scrollHeight") ) * $(this).parent().height();
//pad = $(this).css("padding-bottom").match(/[-\d]+/g)[0]*1+$(this).css("padding-top").match(/[-\d]+/g)[0]*1;
sTop = ( $(this).scrollTop() / ( $(this).prop("scrollHeight") - $(this).outerHeight() ) * ( $(this).height() - scrollerHeight) );
console.log($(this).scrollTop());
$(this).parent().children(".scrollbar").children(".scroller").css({
margin:sTop+"px"+" 0 0 0"
});
});
$(".scrollbar-vertical").parent().children(".content").each(function(){
scrollerHeight = ( $(this).parent().height() / $(this).prop("scrollHeight") ) * $(this).parent().height();
$(this).parent().children(".scrollbar").children(".scroller").css({
height:scrollerHeight
});
pad = $(this).css("padding-bottom").match(/[-\d]+/g)[0]*1+$(this).css("padding-top").match(/[-\d]+/g)[0]*1;
if($(this).prop("scrollHeight") - pad <= $(this).height()){
$(this).parent().children(".scrollbar").hide();
}
});
.example{
width:300px;
height:100px;
overflow:hidden;
position:relative;
background:#eee;
}
.content{
width:100%;
height:100%;
overflow:scroll;
padding:0 100px 100px 0;
margin:0 100px 100px 0;
float:left;
}
.scrollbar-vertical{
width:5px;
height:100%;
position:absolute;
float:left;
right:0;
}
.scrollbar{
transition:0.3s;
background:transparent;
}
.scrollbar:hover{
background:rgba(0,0,0,0.2) !important;
}
.scrollbar-vertical .scroller{
width:100%;
min-height:10px;
background:#333 !important;
}
.scrollbar-vertical:hover{
width:10px;
}
.scrollbar-horizontal{
height:5px;
width:100%;
position:absolute;
float:left;
bottom:0;
}
.scrollbar-horizontal:hover{
height:10px;
}
.scrollbar-horizontal .scroller{
height:100%;
min-width:10px;
background:#333 !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class = "example">
<div class = "content">
content..<br>
content..<br>
content..<br>
content..<br>
content..<br>
content..<br>
</div>
<div class = "scrollbar scrollbar-vertical">
<div class = "scroller"></div>
</div>
</div>
This seems to work fine when the overflow-y: scroll is given for the .content but fails when overflow: scroll is given.
But even when the property overflow: scroll is given the scrollbar works fine in the developer mode in chrome browser.I have traced the problem to be the $(this).scrollTop() which is increased by 17 when not in developer mode.can anyone explain why this is happening? any help is appreciated
codepen
17px is the dimension of a scrollbar in Chrome on desktop (pointer type) displays. This amount of pixels is added to the actual dimension of your container when a scrollbar is present. And, in your example, it's present because you set it to always visible using overflow:scroll.
So the width of a vertical scrollbar is 17px. And the height of a horizontal scrollbar is 17px, in Chrome, on desktops.
The bars are hidden in developer mode because yo uhave pressed "Toggle device toolbar" - enabling preview of touch type devices when in developer mode. Therefore, Chrome adds mobile/touch scrollbars, which are rendered above the content and only visible when used. If your content does not require scrollbars (there's nothing to scroll) they are not shown at all, even if you set overflow: scroll; on the item.
You can toggle the device toolbar by pressing Ctrl + Shift + M while in developer mode.
Related
I have been trying to put an element to fixed position within a given scroll height with Javascript. Outside of this height range, the position should be back to relative.
Here is what I have done so far. The position:fixed is inside the about-option class. When it gets to 4680, the class is added.
How do I make it have a height end-point of 5800 i.e 4680 - 5800, and also remove the class outside this height range?
window.onscroll = function () {
myFunction();
};
function myFunction() {
if (
document.documentElement.scrollTop > 4680 ||
document.body.scrollTop > 4680
) {
document.getElementById("about-txt").classList.add("about-option");
} else {
document.getElementById("about-text").className = "";
}
}
css
.about-option {
position: fixed;
top: 20%;
width: 40%;
right: 7%;
I guess you are trying to do what position sticky does: once the element hits the window's top boundery it starts sticking and if you scroll to the inverse way, it goes back to move together with content. Like here:
https://codepen.io/elad2412/pen/QYLEdK
<main class="main-container">
<header class="main-header">HEADER</header>
<div class="main-content">MAIN CONTENT</div>
<footer class="main-footer">FOOTER</footer>
</main>
body{color:#fff; font-family:arial; font-weight:bold; font-size:40px; }
.main-container{ max-width:600px; margin:0 auto; border:solid 10px green; padding:10px; margin-top:40px;}
.main-container *{padding:10px;background:#aaa; border:dashed 5px #000;}
.main-container * + *{margin-top:20px;}
.main-header{
height:50px; background:#aaa; border-color:red;
}
.main-content{
min-height:1000px;
}
.main-header{position:-webkit-sticky; position:sticky; top:0;}
The trick part is to remember to add a container outside the sticky element, otherwise, it will not work.
I hope it helps!
I encountered a problem where I need to know of the height of horizontal scrollbar.
This Q&A suggests that you should use clientHeight property and calculate difference. Unfortunately this does not work anymore as is evident here https://jsfiddle.net/fn8naww8/
So how can I get the height of scrollbar?
EDIT: OSX does not differentiate between offsetHeight and clientHeight.
html:
<div id="wrapper">
<div id="content"></div>
</div>
css:
#wrapper{
height:100px;
width:100%;
overflow-x:auto;
}
#content{
height:100%;
width:200%;
background:linear-gradient(to right, red , yellow);
}
Try with:
var horizontalScrollbarHeight = wrapper.offsetHeight - wrapper.clientHeight;
or like:
var horizontalScrollbarHeight = wrapper.offsetHeight - parseInt(window.getComputedStyle(wrapper, null).getPropertyValue("height"), 10);
Both will return ~17 if the scrollbar size was not altered by CSS like by using ::-webkit-scrollbar
https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
console.log(window.getComputedStyle(document.querySelector("#wrapper")).height);
console.log(window.getComputedStyle(document.querySelector("#content")).height);
*{
box-sizing: border-box;
}
#wrapper{
height:100px;
width:100%;
overflow-x:auto;
}
#content{
height:100%;
width:200%;
background:linear-gradient(to right, red , yellow);
}
<div id="wrapper">
<div id="content"></div>
</div>
This will return 100px for wrapper and 83px for inner.
There is a magic number: “17px”.
Seems this height/width does not change even if you resize the browser window.
And it works on Chrome fine with my test.
This question builds upon that one, where in order to apply full screen width to a child of a non full width parent element, the following rule is used on the child element:
width: 100vw;
margin-left: calc(-50vw + 50%);
As shown in this Fiddle, this solution doesn't work in the presence of a vertical scrollbar though: 100vw doesn't take the scrollbar into account and hence the child element ends up being wider than the screen (note: works perfectly without scrollbar).
Is there a way to solve this problem so that the child element takes exactly full screen width? If not in pure CSS then with JS?
Note: an overflow rule on body isn't acceptable in my case as I need the child to fill the exact width of the screen.
https://jsfiddle.net/k3nvkL35/4/
One of the issues you'll come across with the solution here is that I believe scrollbar widths are not universal, and so you may need to implement some conditional logic to affect width/margin based on that.
That being said, you may find this useful. The function below will check to see if the document has a vertical scrollbar by comparing the document's height to the window's height. Based on the existence of said scrollbar, it will modify the child's width and margins to fit the window.
Again, it likely requires tweaking, though it should provide a decent foundation.
function adjustWidth() {
if ($(document).height() > $(window).height()) {
$(".child").css({
"width": "calc(100vw - 18px)",
"margin-left": "calc(-50vw + 50% + 9px)"
});
} else {
$(".child").css({
"width": "",
"margin-left": ""
})
}
}
$(window).resize(adjustWidth).trigger("resize");
.parent {
width: 500px;
height: 500px;
margin: 0 auto;
border: 3px solid green;
}
.child {
height: 100px;
background: red;
width: 100vw;
margin-left: calc(-50vw + 50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
<div class="child">
content
</div>
</div>
Simple. Since the parent isn't positioned in any way, then the child can be positioned absolutely. No messing with calc or otherwise, works everywhere.
.child {
height: 100px;
background: red;
position:absolute;
left:0;
right:0;
}
Here is a working fiddle:
https://jsfiddle.net/vgbr6qw2/
I found this solution, which was sourced by this guy, but I don't know who originally did it. I haven't fully tested it, so it may not work in all browsers. I know the vw unit isn't supported in IE8, as if anyone cares.
body {
margin:0;
}
.wrapper {
width:100%;
max-width:400px;
margin:0 auto;
background:pink;
/* margin is for display purposes on stack overflows fullscreen snippet view */
margin-top:80px;
}
.full-width {
width:100vw;
margin-left:-50vw;
left:50%;
background:red;
position:relative;
color:white;
}
<div class="wrapper">
<span>Hi. I'm a paragraph.</span>
<div class="full-width">
<p>You aint no paragraph, sucka!</p>
</div>
<strong>Be quiet, you weak losers.</strong>
</div>
I currently have a mobile website project in which I'm creating panels such that one panel can be viewed at a time, where when a user swipes left or right, the panel slides offscreen and a new panel slides in. Everything works fine on Android, and even behavior is acceptable on iPhone.
However, scrolling on iPhone seems to lack momentum. In other words, when "flicking" the panel up / down, it scrolls on Android natively, but on iPhone it seems to lose momentum very quickly. I'd like to find a simple CSS or combo CSS / JS solution that works, without including additional libraries if possible.
Here's the basic structure of the site:
<html>
<head>Head stuff here</head>
<body>
<div class="container">
<div class="headbox">Fixed position menu here</div>
<div id="pages">
<div class="page">Page panel here</div>
<div class="page">Page panel here</div>
<div class="page">Page panel here</div>
</div>
<div class="bottommenu">Fixed position bottom menu here</div>
</div>
</body>
</html>
Here is the basic CSS:
body {
width:100%;
overflow-x:hidden;
font-size:17px;
border-collapse:collapse;
}
.container {
width:100%;
height:100%;
overflow-x:hidden;
overflow-y:scroll;
position:relative;
/*-webkit-perspective:1000;
-webkit-backface-visibility:hidden;*/
}
.headbox {
font-size:17px;
height:2.3529em;
width:100%;
top:0;
position:fixed;
text-align:center;
color:#fff;
z-index:1;
}
#pages {
width:100%;
height:100%;
white-space:nowrap;
font-size:0;
-webkit-backface-visibility:hidden;
-webkit-transform-style:preserve-3d;
position:relative;
-webkit-transform:translate3d(-100%,0,0);
-moz-transform:translate3d(-100%,0,0);
-ms-transform:translate3d(-100%,0,0);
-o-transform:translate3d(-100%,0,0);
transform:translate3d(-100%,0,0);
}
.page {
width:100%;
height:100%;
display:inline-block;
vertical-align:top;
position:relative;
white-space:normal;
background:#fff;
font-size:17px;
}
.bottommenu {
position:fixed;
bottom:0;
left:0;
width:100%;
height:.2em;
transition:height 400ms;
-webkit-transition:height 400ms;
-moz-transition:height 400ms;
-ms-transition:height 400ms;
-o-transition:height 400ms;
z-index:1;
}
And finally, the listener for scrolling, which shouldn't interfere with CSS or the ability to repaint, but maybe I am missing something:
var that = this;
$(document).scroll(function(){
if (!that.direction && !that.loading) {
that.direction = 'vertical';
that.moving = true;
if (that.scrolling) { clearTimeout(that.scrolling); }
that.scrolling = setTimeout(function() {
that.direction = false;
that.sliding = 0;
that._getMore();
that.moving = false;
},500);
}
});
Any ideas? I've tried numerous variations of -webkit-overflow-scrolling:touch;, overflow-y:scroll;, and other possible hacks / fixes / supported syntax, but nothing seems to help. I need the content to scroll within the body tag so that on iPhone the screen resizes itself on scroll, otherwise I'd use a scrollable div. This is not an option.
I guess problem with loss of native elastic scrolling within container with position: relative; overflow: hidden.
Try -webkit-overflow-scrolling: touch; for .container.
I have a modal that pops up on an onclick event. Basically it adds a greyed out layer over the page, then adds a modal div one z-index higher over the grey. The problem I am running into is for smaller screen sizes you can scroll down the body.
I have tried toggling
body { overflow:hidden }
this works except for when the modal has more content that needs to be seen that exceeds the initial view. Ideally you would be able to see only the modal on smaller screens and scroll down it if needed. Thanks.
Here's my attempt.
HTML
<div class = "popup">
<div class = "over"></div>
<div class = "window">
<button class = "close">Close</button>
<p>Filler</p>
<p>Filler</p>
<p>Filler</p>
<button class = "close">Close</button>
</div>
</div>
<div class = "content">
<p>Filler</p>
<button class = "pop">Popup</button>
<p>Filler</p>
<p>Filler</p>
<button class = "pop">Popup</button>
<p>Filler</p>
</div>
CSS
body {
margin:0;
}
p {
margin:0;
height:200px;
background-color:yellow;
}
.popup {
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
display:none;
z-index:1;
}
.over {
width:100%;
height:100%;
background-color:gray;
opacity:0.5;
position:absolute;
z-index:-1;
}
.window {
border:1px solid black;
width:50%;
height:100%;
overflow:auto;
margin:0 auto;
background-color:orange;
}
.content.paused {
position:fixed!important;
width:100%;
height:1000%;
overflow:hidden;
z-index:0;
}
JQUERY
var scroll;
$('.pop').click (function () {
scroll = $(document).scrollTop ();
$('.popup').show ();
$('.content').offset ({top:-scroll}).addClass ('paused');
});
$('.close').click (function () {
$('.popup').hide ();
$('.content').removeClass ('paused').removeAttr ('style');
$(document).scrollTop (scroll);
});
This requires the page content to be inside a div that is separate from the popup. When you click the button, the current scroll position is saved, then the page content is positioned fixed and moved above the top of the page by the same amount as the scroll. So if you scrolled down 100px, the top of the content will be 100px above the top of the screen, to preserve the visual position of the content. The content will no longer be scrollable because I set the height to be insanely large.
The popup will just be any regular div, with a max height and scrollbars if needed.
When you close the popup, the page content is restored to its original state, the fixed position is removed, top displacement removed, and the page's scroll position is set back to what it was before.
Try to add these attributes to your modal container div:
.modalContainer{
max-width: 500px; //maximum width of the size of the modal
position: relative;
width: 85%; //can be how much of the screen you want it to take up
}