CSS: Visually hide the y-axis scrollbar without affecting x-axis scrollbar - html

Requirements
Visually remove the y-axis scrollbar from a div element
y-axis must still be scrollable, so overflow-y: hidden will not work
x-axis scrollbar must remain intact so -webkit-scrollbar { display: none; } will not work because it removes the x-axis scrollbar as well.
Solution Constraints
Must work in recent versions of Chrome and Safari (not concerned about any other browsers)

Answer to my own question:
I was actually able to accomplish this by using a combination of CSS and Javascript.
I was able to apply an overflow-y: hidden style to the div with the y-axis scrollbar I wanted to hide, and add a custom event listener to that div.
Disclaimer: This solution does not provide pageUp/pageDown, or arrow keys functionality. You will need additional event listeners to get the scroll to reflect those events.
const div = document.getElementById('elementId');
div.addEventListener('mousewheel', ($event) => {
// prevent the page from scrolling when you scroll on an
// element with a style of overflow-y: hidden
$event.preventDefault();
// Calculate and set the scroll position
div.scrollTop = div.scrollTop - $event.wheelDelta;
});

Related

CSS: Disable bounce effect for scroll on iOS 13

In Safari 13 release notes it is stated that there is no longer the need to apply the following to an element to enable the bounce scroll effect:
div {
overflow-x: scroll;
-webkit-overflow-scrolling: touch; /* No longer needed */
}
However, I can now no longer disable this effect with the following code:
div {
overflow-x: scroll;
-webkit-overflow-scrolling: auto;
}
I need this for a carousel I am working on. Any idea on how to fix it?
I think you should try to change that using the overflow property that in Safari blocks the bouncing scroll behaviour. To do that in the parent container of your scrolling div you have to set:
overflow: hidden;
and then in your div set something like this:
div {
overflow: auto;
}
Polyfilling this CSS property in Safari is pretty tricky.
For non-scrollable elements, you can prevent scroll chaining by simply turning off touch gestures. You can do that with a CSS property that is supported by Safari: touch-action: none.
But for scrollable elements, JavaScript will be required.
Remember that scroll chaining occurs when you reach the bounds of the element. So we need to ensure that the user is never able to fully scroll to the top or bottom. Doing this the wrong way can cause UX problems, because the user will clearly be fighting against the default inertia scroll.
So here's the trick:
Create an inner element that is at least 3px taller than the size of its scrolling parent, to force the area to get the overscroll behavior.
Immediately set the scroll position to 1px to prevent scroll chaining when scrolling up
With JavaScript, catch when the scroll position is exactly 0 or exactly at the bottom. After a requestAnimationFrame, set the scroll position to 1px from either the top or bottom.
The container will still get the inertia scroll (the user won't have to fight it) but it won't trigger scroll chaining.
Here's the JavaScript function:
this.addEventListener('scroll', async handleScroll() {
await new Promise(resolve => window.requestAnimationFrame(resolve))
const {
scrollTop,
scrollLeft,
scrollHeight,
clientHeight
} = this
const atTop = scrollTop === 0
const beforeTop = 1
const atBottom = scrollTop === scrollHeight - clientHeight
const beforeBottom = scrollHeight - clientHeight - 1
if (atTop) {
this.scrollTo(scrollLeft, beforeTop)
} else if (atBottom) {
this.scrollTo(scrollLeft, beforeBottom)
}
}
source: https://dev.to/mpuckett/the-holy-grail-web-app-shell-with-header-and-footer-for-iphone-549j
css overscroll-behavior is now supported in iOS 16. If you are targeting > iOS 16 devices, to prevent bounce effect when content inside overflowing parent reaches start or end, add following CSS to the div with overflow : scroll
div {
overscroll-behavior: none;
overflow : scroll
}
Tested in iOS 16 and above.
I don't know if i really understand this correct, but here it goes! :)
Can't you just remove that line of code from your file?
You could also try to write -webkit-overflow-scrolling: auto; !important
Hope this helped :

Preventing horizontal drag scrolling on a 100% width page

I've got a page design that uses CSS keyframes to make a min-height: 100% <section> element containing page content slide in from the right. Once the element has animated to its final position, it is possible to "drag-scroll" the page horizontally by selecting and dragging the text, which I want to avoid.
Both the <html> and <body> elements are set to overflow-x: hidden;, which works for preventing scrollbars but still allows scrolling functionality. I do need users to be able to scroll the <section> element vertically.
I'm assuming the problem is caused by the initial translateX value in the keyframe animation, but I'm not sure how to prevent the horizontal drag scrolling.
Here's a jsfiddle demonstrating the problem.
I appreciate any input.
Perhaps a javascript solution? How is the following:
function bindEvent(e, eventName, callback) {
if(e.addEventListener) // new browsers
e.addEventListener(eventName, callback, false);
else if(e.attachEvent) // IE
e.attachEvent('on'+ eventName, callback);
};
bindEvent(document.body, 'scroll', function(e) {
document.body.scrollLeft = 0;
});

How to turn off scrolling in parent window?

I have a <select> box with many options, and you can scroll through these. When you scroll to the bottom of the options list and continue scrolling, the scrolling "overflows" into the parent window, and scrolls the window down instead. Is there a way to turn this off, i.e. when you scroll to the bottom scrolling down is disabled?
Here is a fiddle. To get the effect I describe, mouse over the multiple select and scroll down (using the trackpad, scroll wheel, etc) to the bottom, then continue scrolling. The entire page will scroll. My desired behavior is for the entire page not to scroll when you reach the bottom of the select options.
The only way to achieve what you want is to use javascript. The logic is pretty simple, on hover, you can add overflow: hidden; to the body, then onblur of the select element, you remove the overflow value.
The code would look something like this (give your select box an id of selectbox):
document.getElementById('selectbox').onmouseenter = function(){
document.body.style.overflow = 'hidden';
};
document.getElementById('selectbox').onmouseout = function(){
document.body.style.overflow = 'auto';
};
demo: http://jsfiddle.net/LRCKn/6/ - you just need to get it to apply the css change on the options elements as well.

How do I hide a scrollbar using CSS?

I have a div that has a lot of content and hence scrolls.. How can I hide the scrollbar such that it is not visible. EDIT: I do want scrolling to work! So.. Scrolling with no scrollbar?
eg
.scrolling_div {
overflow:auto;
/*something else to hide the scrollbar?*/
}
Ok, I spent sometime to write minimal code.
Check DEMO. Mouse over the div and scroll to see the scroller.
Note that this using an external plugin to listen to mousewheel event.
DEMO page for the plugin
overflow:hidden should hide the scrollbar.
.scrolling_div {
overflow: hidden;
}
overflow can take any one of the below values,
visible
Default value. Content is not clipped, it may be rendered outside the content box.
hidden
The content is clipped and no scrollbars are provided.
scroll
The content is clipped and desktop browsers use scrollbars, whether or not any content is clipped. This avoids any problem with scrollbars appearing and disappearing in a dynamic environment.Printers may print overflowing content.
auto
Provide scrollbars if content overflows.
Reference
overflow: auto; means "show a scrollbar if necessary". Change it to overflow: hidden; to disable scrolling.
EDIT: Okay, you want to make a custom scrollbar. Then see this sample jsFiddle for how to get started - it includes mouse wheeling and dragging of the scrollbar.
You can try this:
html {
overflow: hidden;
}
it will remove the scrollbar from all the window.
Otherwise if you need it only on a specific div:
.scrolling_div {
overflow: hidden;
}
Use a wrapper which covers the element you want to be scrollable without a scrollbar, and let the wrapper be narrower than the element to scroll, in the horizontal basis. This is what I mean: http://jsfiddle.net/FlagelloDiDio/EdgTt/
It really depends on what you are going for. see here
overflow:hidden; may be what you want.
If you want to dip into css3, you can play with overflow-x and overflow-y for even more options.
The only way to hide the scrollbar is to make the content non-scrollable and just cut off if it exceeds the height (overflow: hidden). Honestly, why would you want to have a page that is scrollable that doesn't have a scrollbar? That would confuse the heck out of any visitors. There's no way you can do this with CSS.
As far as customizing the scrollbar, there are JavaScripts out there to do that. But make sure that if the user has it disabled, they can still properly scroll the page without it.

Prevent a centered layout from shifting its position when scrollbar appears

My page layout looks something like this:
<style type="text/css">
#content-wrap
{
margin: 0 auto;
width: 800px;
}
</style>
<div id="content-wrap">
</div>
You'll notice that the content-wrap div shifts its position a tad bit when the vertical scrollbar appears. One scenario is when the browser starts to progressively render the page without displaying the vertical scrollbar, then determines that a scrollbar is needed because the content is taller than the "fold". This shifts the div about 10px towards left.
What is the best way to tackle this problem without forcing the browser to always display the scrollbar?
I'm afraid the best way to solve this is to force the scroll bar to be visible at all times with html {overflow-y: scroll;}. The problem you have is that the "available area" shrinks with say 10 px when the scroll bar appear. This cause the calculated margin on your left side to shrink with half the width of the scroll bar, thus shifting the centered content somewhat to the left.
A possible solution might be to calculate the margin with JavaScript instead of using margin: 0 auto; and somehow compensate for the "lost" pixels when the scroll bar appear, but I'm afraid it will be messy and the content will probably move a little bit anyway while you calculate and apply the new margin.
If your site is "responsive" (reacts to width):
Step 1: Add width: 100vw to a wrapper element. This makes it as wide as the viewport, ignoring the appearance of a scrollbar.
Step 2: Add overflow-x: hidden to the content element. This will remove the horizontal scrollbar (created when vertical scrollbar appears, to allow the user to "look under" it).
"wrapper element" is in our case referring to another div around your #content-wrap
Will work for your case too, tested:
<style type="text/css">
body {
overflow-x: hidden;
}
#wrap-wrap {
width: 100vw;
}
#content-wrap
{
margin: 0 auto;
width: 800px;
}
</style>
<div id="wrap-wrap">
<div id="content-wrap">
</div>
</div>
Make sure nothing useful on your page is wide enough to get caught under the scrollbar.
For example, you can ensure that the sum of (horizontal padding + border + horizontal margin) of the content element is wider than the scrollbar).
If your site is fixed width + centered (your case):
html {
margin-left: calc(100vw - 100%);
margin-right: 0;
}
This will add a left margin equal in width to the scrollbar when it appears. Which is 0 when it does not. Taken from here, but tested.
You must use:
html {
overflow-y: overlay;
}
Only supported by WebKit (Safari) or Blink (Chrome, Opera)
Use jquery and put this in the start of your tag:
<script type="text/javascript">
function checkheight(){
if ($(document).height() > $(window).height()) {
//that is if there is vertical scrollbar
document.getElementById('yourcenteredcontainer').style.paddingLeft='8px';
//8px because the scrollbars are (?always?) 16px
}else{
document.getElementById('yourcenteredcontainer').style.paddingLeft='0px';
}
}
</script>
and call the function checkheight(); in the end of your tag plus wherever you have onclick (or other) events that make the page longer or shorter in height.
If you can use Javascript, you can set the width of the content-wrap to the inner width of the window minus the standard width of a scrollbar.
You will run into some problems though.
The user will have to have Javascript enabled
You don't know what the width of the vertical scrollbar is, especially if the scrollbar isn't there! So you will have to guess. 20px seems like a good guess.
Different browsers have different ways of telling you want the inner width of the window is.
So if you can live with all that, you can do something like this (in pseudo code)
if window.innerWidth is defined :
set the width of the div to window.innerWidth-20px
else if we're running on Internet Explorer :
set the width to document.documentElement.offsetWidth-20px
otherwise :
we're out of luck and we best leave the width as is.
First I would recommend optimizing the HTML so that it won't take so long to load/render. If load/render is fast the scrollbar won't appear "too late". What is it that takes long to load/render? Check the network tab in chrome debug tools (F12). Do an audit in Chrome debug tools.
There are multiple things that could make the document "reflow", and the scrollbar appear even though the browser could have known the necessary measurements right from the start. Are you using tables for layout - don't! They may need multiple passes of rendering. Do you have images without width/height specified? Then the document will need to be rerendered when each image loads. Specify <img ... style="width: ..px; height: ..px">. Is the CSS sane and efficient?
If you can't get load/rendering speed down I think your best bet is to not use the browser's scrollbar if javascript is enabled. That way you can control it and place it absolutely positioned so that it won't affect horizontal positioning.
Let your slider start of with display: none. Monitor dom ready event as well as image load events as well as window resize events. When the page has been loaded, images have been loaded and when window gets resized just run the same function every time. It would determine if the scrollbar is needed and either display it or hide it.
You could use JQuery UI Slider for example and set it's maxValue to $(document).height() - $(window).height(), monitor the slider change event and then scroll the body to the value of the slider and so forth.
If javascript is disabled the fallback will be the regular scrollbar and there's nothing you can do about the slight horizontal shift then.
But really I think the problem of the horizontal shift is too small to spend time fixing with a custom scrollbar, and check that it actually works well on all platforms etc. Do HTML/CSS optimizations first.
You can try this solution: https://stackoverflow.com/a/67213174/14302216
But the widths can't be relative. Probably, width:100vw will work for the parent, but I'm not sure how you would set the child width. I'm afraid calc(100vw-16px) will not work. But if you can set like widht:800px for the child, it will be fine!