WebKit/Blink's (Safari/Chrome) default behaviour on MacOS since 10.7 (Mac OS X Lion) is to hide scroll bars from trackpad users when they're not in use. This can be confusing; the scroll bar is often the only visual cue that an element is scrollable.
Example (jsfiddle)
HTML
<div class="frame">
Foo<br />
Bar<br />
Baz<br />
Help I'm trapped in an HTML factory!
</div>
CSS
.frame {
overflow-y: auto;
border: 1px solid black;
height: 3em;
width: 10em;
line-height: 1em;
}
WebKit (Chrome) Screenshot
Presto (Opera) Screenshot
How can I force a scroll bar to always be displayed on a scrollable element in WebKit?
The appearance of the scroll bars can be controlled with WebKit's -webkit-scrollbar pseudo-elements [blog]. You can disable the default appearance and behaviour by setting -webkit-appearance [docs] to none.
Because you're removing the default style, you'll also need to specify the style yourself or the scroll bar will never show up. The following CSS recreates the appearance of the hiding scroll bars:
Example (jsfiddle)
CSS
.frame::-webkit-scrollbar {
-webkit-appearance: none;
}
.frame::-webkit-scrollbar:vertical {
width: 11px;
}
.frame::-webkit-scrollbar:horizontal {
height: 11px;
}
.frame::-webkit-scrollbar-thumb {
border-radius: 8px;
border: 2px solid white; /* should match background, can't be transparent */
background-color: rgba(0, 0, 0, .5);
}
.frame::-webkit-scrollbar-track {
background-color: #fff;
border-radius: 8px;
}
WebKit (Chrome) Screenshot
For a one-page web application where I add scrollable sections dynamically, I trigger OSX's scrollbars by programmatically scrolling one pixel down and back up:
// Plain JS:
var el = document.getElementById('scrollable-section');
el.scrollTop = 1;
el.scrollTop = 0;
// jQuery:
$('#scrollable-section').scrollTop(1).scrollTop(0);
This triggers the visual cue fading in and out.
Here is a shorter bit of code that reenables scroll bars across your entire website. I'm not sure if it's much different than the current most popular answer but here it is:
::-webkit-scrollbar {
-webkit-appearance: none;
width: 7px;
}
::-webkit-scrollbar-thumb {
border-radius: 4px;
background-color: rgba(0,0,0,.5);
box-shadow: 0 0 1px rgba(255,255,255,.5);
}
Found at this link: http://simurai.com/blog/2011/07/26/webkit-scrollbar
Browser scrollbars don't work at all on iPhone/iPad. At work we are using custom JavaScript scrollbars like jScrollPane to provide a consistent cross-browser UI: http://jscrollpane.kelvinluck.com/
It works very well for me - you can make some really beautiful custom scrollbars that fit the design of your site.
Another good way of dealing with Lion's hidden scroll bars is to display a prompt to scroll down. It doesn't work with small scroll areas such as text fields but well with large scroll areas and keeps the overall style of the site. One site doing this is http://versusio.com, just check this example page and wait 1.5 seconds to see the prompt:
http://versusio.com/en/samsung-galaxy-nexus-32gb-vs-apple-iphone-4s-64gb
The implementation isn't hard but you have to take care, that you don't display the prompt when the user has already scrolled.
You need jQuery + Underscore and
$(window).scroll
to check if the user already scrolled by himself,
_.delay()
to trigger a delay before you display the prompt -- the prompt shouldn't be to obtrusive
$('#prompt_div').fadeIn('slow')
to fade in your prompt and of course
$('#prompt_div').fadeOut('slow')
to fade out when the user scrolled after he saw the prompt
In addition, you can bind Google Analytics events to track user's scrolling behavior.
Related
I'm working in an Angular 9 project, using Material (SCSS stylesheets).
I have a Material select, there's many options and so you're able to scroll through them. The problem is, unless you knew there were other options, or happened to try a scroll, you wouldn't know the list extends. I want to resolve this by having the scroll bar always show.
How can I make the scroll always be visible in the material select element. I'm guessing I'll use some sort of style. I'm also using scss stylesheets.
Here's what shows now:
I want the scroll to always show, not just when you literally scroll down the element:
I also make a quick https://stackblitz.com/edit/always-show-scroll-material-select
The scroll is not showing because you are probably using the trackpad or a magic mouse. Using an external mouse will show the scrollbar just setting "overflow" to "auto" or "scroll".
If you want to show also the scrollbar using the trackpad or the magic mouse, you can still do it using the -webkit-scrollbar pseudo-element
In this post is also explained:
Preventing scroll bars from being hidden for MacOS trackpad users in WebKit/Blink
In your particular case you could achieve this using these css lines:
::ng-deep .mat-select-panel::-webkit-scrollbar {
-webkit-appearance: none;
}
::ng-deep .mat-select-panel::-webkit-scrollbar:vertical {
width: 11px;
}
::ng-deep .mat-select-panel::-webkit-scrollbar:horizontal {
height: 11px;
}
::ng-deep .mat-select-panel::-webkit-scrollbar-thumb {
border-radius: 8px;
border: 2px solid white; /* should match background, can't be transparent */
background-color: rgba(0, 0, 0, .5);
}
I am styling some scrollbars on a webpage for webkit, and I want the track to be semi-transparent so that some of the background image bleeds through, but when I insert an RGBa value, it treats it just like an RGB value (without any alpha-channel). Does ::-webkit-scrollbars not accept RGBa? I know it doesn't accept anything like transitions, so did WebKit skip out on other cool effects too?
Code:
::-webkit-scrollbar {
-webkit-appearance: none;
width: 8px;
}
::-webkit-scrollbar-track {
background-color: rgba(57,57,57, .6);
border-radius: 8px;
}
::-webkit-scrollbar-thumb {
border-radius: 8px;
background-color: rgba(156, 156, 156, .6);
}
(But - on my side - it is treating rgba as just a plain rgb value)
Checkout my vertical jsfiddle for doing it with a vertical page. I setup a transparent track with a background image with the following:
::-webkit-scrollbar-track {
background: rgba(57,57,57, .6);;
}
For a horizontal page, checkout this horizontal fiddle. The difference with the horizontal code is I setup the page to be 100% height:
body, html, .scrolls {
height: 100%;
}
Then I wrapped the page content in a div, which is where the scrolling will happen, not on the page itself, like so:
.scrolls {
overflow-x: scroll;
overflow-y: hidden;
white-space:nowrap;
background-image: url('http://www.evokia.com/images/large-background.jpg');
}
This is the workaround for the fact that it appears that the horizontal scroll on the page never gets the background of the page, so in order to get the transparent track we needed to create the scroll in the page.
I'm pretty sure webkit does support RGBa values, I've used body::-webkit-scrollbar-track{} which has worked fine.
I've also used the Jscroll pane plugin, which I've found to be very intuitive and this does support rgba values too. This can also support full webpage customised scroll bars and IE 7+ as well.
Is it possible to see your code to see if ther are any issues?
WebKit/Blink's (Safari/Chrome) default behaviour on MacOS since 10.7 (Mac OS X Lion) is to hide scroll bars from trackpad users when they're not in use. This can be confusing; the scroll bar is often the only visual cue that an element is scrollable.
Example (jsfiddle)
HTML
<div class="frame">
Foo<br />
Bar<br />
Baz<br />
Help I'm trapped in an HTML factory!
</div>
CSS
.frame {
overflow-y: auto;
border: 1px solid black;
height: 3em;
width: 10em;
line-height: 1em;
}
WebKit (Chrome) Screenshot
Presto (Opera) Screenshot
How can I force a scroll bar to always be displayed on a scrollable element in WebKit?
The appearance of the scroll bars can be controlled with WebKit's -webkit-scrollbar pseudo-elements [blog]. You can disable the default appearance and behaviour by setting -webkit-appearance [docs] to none.
Because you're removing the default style, you'll also need to specify the style yourself or the scroll bar will never show up. The following CSS recreates the appearance of the hiding scroll bars:
Example (jsfiddle)
CSS
.frame::-webkit-scrollbar {
-webkit-appearance: none;
}
.frame::-webkit-scrollbar:vertical {
width: 11px;
}
.frame::-webkit-scrollbar:horizontal {
height: 11px;
}
.frame::-webkit-scrollbar-thumb {
border-radius: 8px;
border: 2px solid white; /* should match background, can't be transparent */
background-color: rgba(0, 0, 0, .5);
}
.frame::-webkit-scrollbar-track {
background-color: #fff;
border-radius: 8px;
}
WebKit (Chrome) Screenshot
For a one-page web application where I add scrollable sections dynamically, I trigger OSX's scrollbars by programmatically scrolling one pixel down and back up:
// Plain JS:
var el = document.getElementById('scrollable-section');
el.scrollTop = 1;
el.scrollTop = 0;
// jQuery:
$('#scrollable-section').scrollTop(1).scrollTop(0);
This triggers the visual cue fading in and out.
Here is a shorter bit of code that reenables scroll bars across your entire website. I'm not sure if it's much different than the current most popular answer but here it is:
::-webkit-scrollbar {
-webkit-appearance: none;
width: 7px;
}
::-webkit-scrollbar-thumb {
border-radius: 4px;
background-color: rgba(0,0,0,.5);
box-shadow: 0 0 1px rgba(255,255,255,.5);
}
Found at this link: http://simurai.com/blog/2011/07/26/webkit-scrollbar
Browser scrollbars don't work at all on iPhone/iPad. At work we are using custom JavaScript scrollbars like jScrollPane to provide a consistent cross-browser UI: http://jscrollpane.kelvinluck.com/
It works very well for me - you can make some really beautiful custom scrollbars that fit the design of your site.
Another good way of dealing with Lion's hidden scroll bars is to display a prompt to scroll down. It doesn't work with small scroll areas such as text fields but well with large scroll areas and keeps the overall style of the site. One site doing this is http://versusio.com, just check this example page and wait 1.5 seconds to see the prompt:
http://versusio.com/en/samsung-galaxy-nexus-32gb-vs-apple-iphone-4s-64gb
The implementation isn't hard but you have to take care, that you don't display the prompt when the user has already scrolled.
You need jQuery + Underscore and
$(window).scroll
to check if the user already scrolled by himself,
_.delay()
to trigger a delay before you display the prompt -- the prompt shouldn't be to obtrusive
$('#prompt_div').fadeIn('slow')
to fade in your prompt and of course
$('#prompt_div').fadeOut('slow')
to fade out when the user scrolled after he saw the prompt
In addition, you can bind Google Analytics events to track user's scrolling behavior.
Developing an iPad website I tried to use the CSS property overflow: auto to get the scrollbars if needed in a div, but my device is refusing to show them even if the two fingers scroll is working.
I tried with
overflow: auto;
and
overflow: scroll;
and the result is the same.
I'm only testing on an iPad (on desktop browsers works perfectly).
Any ideas?
Edit following the comment left, kindly, by kritzikratzi:
[Starting] with ios 5beta a new property -webkit-overflow-scrolling: touch can be added which should result in the expected behaviour.
Some, but very little, further reading:
Native momentum scrolling in iOS 5
Original answer, left for posterity.
Unfortunately neither overflow: auto, or scroll, produces scrollbars on the iOS devices, apparently due to the screen-width that would be taken up such useful mechanisms.
Instead, as you've found, users are required to perform the two-finger swipe in order to scroll the overflow-ed content. The only reference, since I'm unable to find the manual for the phone itself, I could find is here: tuaw.com: iPhone 101: Two-fingered scrolling.
The only work-around I can think of for this, is if you could possibly use some JavaScript, and maybe jQTouch, to create your own scroll-bars for overflow elements. Alternatively you could use #media queries to remove the overflow and show the content in full, as an iPhone user this gets my vote, if only for the sheer simplicity. For example:
<link rel="stylesheet" href="handheld.css" media="only screen and (max-device width:480px)" />
The preceding code comes from A List Apart, from the same article linked-to above (I'm not sure why they left of the type="text/css", but I assume there are reasons.
Apply this code in your css
::-webkit-scrollbar{
-webkit-appearance: none;
width: 7px;
}
::-webkit-scrollbar-thumb {
border-radius: 4px;
background-color: rgba(0,0,0,.5);
-webkit-box-shadow: 0 0 1px rgba(255,255,255,.5);
}
I have done some testing and using CSS3 to redefine the scrollbars works and you get to keep your Overflow:scroll; or Overflow:auto
I ended up with something like this...
::-webkit-scrollbar {
width: 15px;
height: 15px;
border-bottom: 1px solid #eee;
border-top: 1px solid #eee;
}
::-webkit-scrollbar-thumb {
border-radius: 8px;
background-color: #C3C3C3;
border: 2px solid #eee;
}
::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.2);
}
The only down side which I have not yet been able to figure out is how to interact with the scrollbars on iProducts but you can interact with the content to scroll it
Solution given by Chris Barr here
function isTouchDevice(){
try{
document.createEvent("TouchEvent");
return true;
}catch(e){
return false;
}
}
function touchScroll(id){
if(isTouchDevice()){ //if touch events exist...
var el=document.getElementById(id);
var scrollStartPos=0;
document.getElementById(id).addEventListener("touchstart", function(event) {
scrollStartPos=this.scrollTop+event.touches[0].pageY;
event.preventDefault();
},false);
document.getElementById(id).addEventListener("touchmove", function(event) {
this.scrollTop=scrollStartPos-event.touches[0].pageY;
event.preventDefault();
},false);
}
}
Works fine for me. Remove event.preventDefault if you need to use some clicks...
The iScroll4 javascript library will fix it right up. It has a hideScrollbar method that you can set to false to prevent the scrollbar from disappearing.
In my experience you need to make sure the element has display:block; applied for the -webkit-overflow-scrolling:touch; to work.
Other 2 peoples on SO proposed possible CSS-only solution to the problem. David Thomas' solution is perfect but has the limit that scrollbar is visible only during scrolling.
In order to have scrollbars always visible, is possible to followin guidelines suggested on the following links:
How can I prevent scroll bars from being hidden for OS X trackpad users in WebKit/Blink?
CSS - Overflow: Scroll; - Always show vertical scroll bar?
make sure your body and divs have not a
position:fixed
else it would not work
Works fine for me, please try:
.scroll-container {
max-height: 250px;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
::-webkit-scrollbar {
width: 15px;
height: 15px;
}
::-webkit-scrollbar-thumb {
border-radius: 8px;
background-color: #C3C3C3;
border: 2px solid #eee;
}
Use this code, it work in ios/android APP webview; It delete some not portable css code;
If you are trying to achieve horizontal div scrolling with touch on mobile, the updated CSS fix does not work (tested on Android Chrome and iOS Safari multiple versions), eg:
-webkit-overflow-scrolling: touch
I found a solution and modified it for horizontal scrolling from before the CSS trick. I've tested it on Android Chrome and iOS Safari and the listener touch events have been around a long time, so it has good support: http://caniuse.com/#feat=touch.
Usage:
touchHorizScroll('divIDtoScroll');
Functions:
function touchHorizScroll(id){
if(isTouchDevice()){ //if touch events exist...
var el=document.getElementById(id);
var scrollStartPos=0;
document.getElementById(id).addEventListener("touchstart", function(event) {
scrollStartPos=this.scrollLeft+event.touches[0].pageX;
},false);
document.getElementById(id).addEventListener("touchmove", function(event) {
this.scrollLeft=scrollStartPos-event.touches[0].pageX;
},false);
}
}
function isTouchDevice(){
try{
document.createEvent("TouchEvent");
return true;
}catch(e){
return false;
}
}
Modified from vertical solution (pre CSS trick):
http://chris-barr.com/2010/05/scrolling_a_overflowauto_element_on_a_touch_screen_device/
I'm currently writing some stylesheets for mobile browsers and have come across a strange issue in the Android browser. When changing the font-size CSS attribute of a text box the box gets bigger to accomodate the larger text. Doing this on a select box however does not change the size of the select box, but the text still gets larger (actually overlapping the top and bottom of the rendered form element).
Can anyone tell me if it's possible to increase the height of select boxes in the Android browser. Or if not point me in the direction of a list of CSS attributes that can be applied to them.
Thanks.
Another option you can use (tested on galaxy S running android version 2.1-update1):
select {
-webkit-appearance: listbox;
}
select, input {
width: 100%;
height: 40px;
line-height:40px;
border: 1px solid #999;
border-radius: 6px;
margin-bottom:10px;
}
This way the inputs and selects all look the same, clicking the select will open the options menu as usual.
This seems to be a browser bug. You can also reproduce it when you set your browser's text size to 'huge' (in settings). I added a new issue and suggest a workaround with a custom background image for now:
<select style="background: url('big-select-bg.png')"/>
try this one:
select{
-webkit-appearance: menulist-text;
}
Set the opacity of the select control to 0
Then place a span contorl styled to look like a textbox behind the select control so that the select control are sits directly on top of the span.
The user won't see the select control but when the user attemps to enter text into the span the dropdown options for the select control will appear.
After the user makes their selection use javascript to update the innerHTML of the span with the value of the select control.
Make sure the dimensions of the span and the select control line up well.
(Do not use an actual texbox control)
mealaroni.com
For me "-webkit-appearance: listbox;" solved the issue not completely.
I had to add a padding attribute additionally:
select {
-webkit-appearance: listbox;
width: 100%;
height: 35px;
line-height: 35px;
border: 1px solid #bbb;
border-radius: 4px;
padding: 0 0 1px 8px;
}