111

I am trying to figure out how to have a scrollable div that only shows its scrollbars when Hovered.

Example is Google Image search, in the image below you can see how the left sidebar does not appear to be scroll-able until you hover the mouse over it.

Is this possible with CSS or is Javascript required? If possible maybe a quick example how to do such a task?

Example

alex
  • 479,566
  • 201
  • 878
  • 984
JasonDavis
  • 48,204
  • 100
  • 318
  • 537

16 Answers16

202

div {
  height: 100px;
  width: 50%;
  margin: 0 auto;
  overflow: hidden;
}

div:hover {
  overflow-y: scroll;
}
<div>
  <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It
    has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop
    publishing software like Aldus PageMaker including versions of Lorem Ipsum.
  </p>
</div>

Would something like that work?

Calvin Froedge
  • 16,135
  • 16
  • 55
  • 61
  • 1
    @saratis: it does... [JS Fiddle demo](http://jsfiddle.net/davidThomas/GXZHk/), albeit only tested in Chrome 16/WinXP currently. – David Thomas Dec 25 '11 at 22:10
  • The support seems pretty decent: http://www.quirksmode.org/css/contents.html#t16 However a fallback to remove overflow: hidden for – Christofer Eliasson Dec 25 '11 at 22:25
  • This works with IE9 and Chrome but broke in Firefox, still pretty good start, thanks – JasonDavis Dec 26 '11 at 00:18
  • Hi @CalvinFroedge is there a way to use auto instead of scroll because I've to use this solution in multiple places and in some places I don't need to scrollbar at all. Thanks in advance. +1 for the above solution though. – Rupam Datta Apr 08 '13 at 09:47
  • 3
    it displays the scrollbar but sometimes the divs under the scrollbar do not update their width after moving mouse out. they remain shrinked with an empty space for scorllbar (tested on firefox and chrome) – Bakhshi Sep 04 '13 at 04:31
  • 1
    @Bakhshi I'm having the same issue I've implemented what's explained in this post and now it's working fine. http://stackoverflow.com/questions/3485365/how-can-i-force-webkit-to-redraw-repaint-to-propagate-style-changes – Jeffpowrs Sep 05 '13 at 17:36
  • 1
    It won't work in most browsers on Mac as they start showing scroll after scrolling itself began, but not on hover – antiplayer Aug 19 '16 at 07:42
  • As a word of caution for followers if you specify `overflow-y: hidden;` inline in the style attribute of an element, it seems to override the hover setting if you have that elsewhere in a separate style block (which it has to be in apparently). As another word of caution, "hover" doesn't work with mobile, and it works great with a mouse but (on most browsers) not with the trackpad (if the mouse is unplugged), even though the trackpad controls the mouse. Odd. – rogerdpack Jul 07 '17 at 18:32
  • 2
    when you hover and the scrollbar is added, the content jumps to the left. Content should remain where it is. – StealthTrails Jan 19 '18 at 18:28
  • 7
    Sorry to raise the dead... but `#div:hover { overflow-y: auto; }` is a more user-friendly solution. Only displays the scrollbar if the window needs it. – barnacle.m Oct 03 '18 at 17:53
83

The answer with changing overflow have a bunch of issues, like inconsistent width of the inner block and triggering of reflow.

There is an easier way to have the same effect that would not trigger reflow ever: using visibility property and nested blocks:

.scrollbox {
  width: 10em;
  height: 10em;
  overflow: auto;
  visibility: hidden;
}

.scrollbox-content,
.scrollbox:hover,
.scrollbox:focus {
  visibility: visible;
}

.scrollbox_delayed {
  transition: visibility 0.2s;
}

.scrollbox_delayed:hover {
  transition: visibility 0s 0.2s;
}
<h2>Hover it</h2>
<div class="scrollbox" tabindex="0">
  <div class="scrollbox-content">Hover me! Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere velit, repellat voluptas ipsa impedit fugiat voluptatibus. Facilis deleniti, nihil voluptate perspiciatis iure adipisci magni, nisi suscipit aliquam, quam, et excepturi! Lorem
    ipsum dolor sit amet, consectetur adipisicing elit. Facere velit, repellat voluptas ipsa impedit fugiat voluptatibus. Facilis deleniti, nihil voluptate perspiciatis iure adipisci magni, nisi suscipit aliquam, quam, et excepturi!</div>
</div>

<h2>With delay</h2>
<div class="scrollbox scrollbox_delayed" tabindex="0">
  <div class="scrollbox-content">Hover me! Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere velit, repellat voluptas ipsa impedit fugiat voluptatibus. Facilis deleniti, nihil voluptate perspiciatis iure adipisci magni, nisi suscipit aliquam, quam, et excepturi! Lorem
    ipsum dolor sit amet, consectetur adipisicing elit. Facere velit, repellat voluptas ipsa impedit fugiat voluptatibus. Facilis deleniti, nihil voluptate perspiciatis iure adipisci magni, nisi suscipit aliquam, quam, et excepturi!</div>
</div>

Another feature of this method is that visibility is animatable, so we can add a transition to it (see the second example in the pen above). Adding a transition would be better for UX: the scrollbar won't appear immediately when hovered just while moving along to another element, and it would be harder to miss the scrollbar when targeting it with mouse cursor, as it won't hide immediately as well.

kizu
  • 42,604
  • 4
  • 68
  • 95
  • So just to clarify: this involves having a dedicated div for the scrollbar? Is this the proper way to do it? – Trace DeCoy Feb 02 '16 at 11:50
  • 2
    I have seen multiple questions on this issue and this answer is actually brilliant. Its cross browser compatible and overall easy and awesome. – Rithwik Oct 18 '17 at 11:53
  • 1
    This solution just saved me so much. I spent hours trying to get a div scrollbar working to display only on hover, but trying to fix the page repositioning on hover wasn't playing nice cross-browser. This fixed it immediately. Thank you! – helloimbarbara Mar 23 '20 at 14:51
  • 4
    The solution may have an issue on touch-devices. Because of `visibility: hidden` the user has to tap in the scrollbox once before scrolling works. My solution was to adapt it as following: `@media (hover: hover) { .scrollbox { visibility: hidden; }}` – Benjamin Freitag Apr 09 '21 at 12:55
12

One trick for this, for webkit browsers, is to create an invisible scrollbar, and then make it appear on hover. This method does not affect the scrolling area width as the space needed for the scrollbar is already there.

Something like this:

body {
  height: 500px;
  &::-webkit-scrollbar {
    background-color: transparent;
    width: 10px;
  }
  &::-webkit-scrollbar-thumb {
    background-color: transparent;
  }
}

body:hover {
  &::-webkit-scrollbar-thumb {
    background-color: black;
  }
}

.full-width {
  width: 100%;
  background: blue;
  padding: 30px;
  color: white;
}
some content here

<div class="full-width">does not change</div>
Alex Tarkowski
  • 195
  • 3
  • 11
  • This doesn't work for me inside a custom element's shadow root like so: `:host:hover::-webkit-scrollbar-thumb {background: blue}`. Nothing happens. It works in this answer with body, but not at all with :host. – trusktr Apr 28 '23 at 02:18
  • OMG, because it should be :host(:hover), not :host:hover. That's not intuitive. – trusktr Apr 28 '23 at 03:33
6

Give the div a fixed height and srcoll:hidden; and on hover change the scroll to auto;

#test_scroll{ height:300px; overflow:hidden;}
#test_scroll:hover{overflow-y:auto;}

Here is an example. http://jsfiddle.net/Lywpk/

Virendra
  • 2,560
  • 3
  • 23
  • 37
5

.scroll {
  height: 140px;
  width: 140px;
  overflow-y: auto;
}

.scroll:active::-webkit-scrollbar-thumb,
.scroll:focus::-webkit-scrollbar-thumb,
.scroll:hover::-webkit-scrollbar-thumb {
    visibility: visible;
}
.scroll::-webkit-scrollbar-thumb {
    background-color: darkgrey;
    visibility: hidden;
}

.scroll::-webkit-scrollbar {
    width: 4px;
    height: 4px;
}
<div class="scroll">
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Reiciendis aliquid recusandae nisi dolore numquam consectetur voluptatibus officia. Velit quod corporis quae quos. Facere, obcaecati? Tenetur obcaecati minima fugit a iste!
  </p>
</div>
Fatih Ertuğral
  • 230
  • 2
  • 4
4
.div::-webkit-scrollbar-thumb {
    background: transparent;
}

.div:hover::-webkit-scrollbar-thumb {
    background: red;
}
  • This doesn’t answer the question, it just changes the scroll bar color. Also, it only applies to mobile WebKit devices and is still in draft. – pygeek Sep 17 '20 at 11:20
3

Since it has not been mentioned yet, a css solution for Firefox, which does not affect the div's size:

div {
    overflow-y: scroll;
    /* Sets Color to Transparent for both the track and the thumb */
    scrollbar-color: transparent transparent;
    /* Optional, provides a smooth transition */
    transition: scrollbar-color .25s ease-in-out;
}

div:hover {
    /* Sets the color back to the default value. You can choose a different color */
    scrollbar-color: initial;
}

You can use this with the ::webkit-scrollbar properties (already answered here) for compatibility.

Xintaur
  • 121
  • 1
  • 6
2

Answer by @Calvin Froedge is the shortest answer but have an issue also mentioned by @kizu. Due to inconsistent width of the div the div will flick on hover. To solve this issue add minus margin to the right on hover

#div { 
     overflow:hidden;
     height:whatever px; 
}
#div:hover { 
     overflow-y:scroll; 
     margin-right: -15px; // adjust according to scrollbar width  
}
Kalim ul Haq
  • 196
  • 1
  • 10
2

I used this method

.content {
  padding: 17px 0 17px 17px;
  width: 300px;
  height: 200px;
  overflow-y: scroll;
  mask-image: linear-gradient(to top, transparent, black),
    linear-gradient(to left, transparent 17px, black 17px);
  mask-size: 100% 20000px;
  mask-position: left bottom;
  -webkit-mask-image: linear-gradient(to top, transparent, black),
    linear-gradient(to left, transparent 17px, black 17px);
  -webkit-mask-size: 100% 20000px;
  -webkit-mask-position: left bottom;
  transition: mask-position 0.3s, -webkit-mask-position 0.3s;
}

.content:hover {
  -webkit-mask-position: left top;
}

@keyframes background {
  from {
    background: pink;
  }
  to {
    background: #c0d6ff;
  }
}

.wrapper {
  float: left;
  animation: background 5s infinite alternate;
}
<div class="wrapper">
  <div class="content">
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
  </div>
</div>
Fahimeh Ahmadi
  • 813
  • 8
  • 13
2

I think something like

$("#leftDiv").mouseover(function(){$(this).css("overflow","scroll");});
$("#leftDiv").mouseout(function(){$(this).css("overflow","hidden");});
Derk Arts
  • 3,432
  • 2
  • 18
  • 36
1

Here's another version of minimal auto-hiding scrollbars without the issues associated with using overflow:hidden;

.minimal-scrollbars{
  scrollbar-width: thin;
  scrollbar-color: #aaa transparent;
  -ms-overflow-style: -ms-autohiding-scrollbar;
}

.minimal-scrollbars::-webkit-scrollbar-track  {
  background-color: transparent;
}

.minimal-scrollbars::-webkit-scrollbar{
  width: .3em;
}

@media(hover:hover){
  .minimal-scrollbars{
    scrollbar-color: transparent transparent;
  }
  .minimal-scrollbars:hover{
    scrollbar-color: #aaa transparent;
  }
  .minimal-scrollbars::-webkit-scrollbar-thumb {
    background-color: transparent;
  }
  .minimal-scrollbars:hover::-webkit-scrollbar-thumb {
    background-color: #aaa;
  }
}
SuprMan
  • 350
  • 4
  • 16
0

If you are only concern about showing/hiding, this code would work just fine:

$("#leftDiv").hover(function(){$(this).css("overflow","scroll");},function(){$(this).css("overflow","hidden");});

However, it might modify some elements in your design, in case you are using width=100%, considering that when you hide the scrollbar, it creates a little bit of more room for your width.

Fabio Nolasco
  • 7,122
  • 6
  • 35
  • 32
0

This will work:

#div{
     max-height:300px;
     overflow:hidden;
}
#div:hover{
     overflow-y:scroll;
}
Jamil Moughal
  • 19
  • 1
  • 6
  • could you add the detail as well? – Muhammad Oct 24 '18 at 14:07
  • 1
    Details??? in first #div statement I have set max-height for div so that I cannot exceed then maximum height and when there are more data than it will be scrollable. I set overflow to hidden. In second statement i set div for hover, when anyone hover div it will show horizantal scroll bar. – Jamil Moughal Oct 24 '18 at 20:08
0
div {
  height: 100px;
  width: 50%;
  margin: 0 auto;
  overflow-y: scroll;
}

div:hover > ::-webkit-scrollbar-thumb   {
  visibility : visible;
}

::-webkit-scrollbar {
   width: 0.5rem;
 }

::-webkit-scrollbar-track {
   margin-left: 1rem;
 }

::-webkit-scrollbar-thumb {
   background: var(--dimGrayColor);
   border-radius: 1rem;
   visibility: hidden;
   transition: 0.3s all linear;
}

if You use overflow: hidden property in div and on hover you show overflow-y: scroll then it produce jerk motion in the div so this is the code which is better I figure out to avoid such kind of useless motion.

0

Here is a version working for chrome/edge/firefox, without the reflow issue

.overflow-auto {
  overflow: auto;
  // scrollbar firefox
  scrollbar-color: transparent transparent;
  // scrollbar chrome/edge
  &::-webkit-scrollbar-track,
  &::-webkit-scrollbar-thumb {
    visibility: hidden;
  }
  &:hover {
    // scrollbar firefox
    scrollbar-color: initial;
    // scrollbar chrome/edge
    &::-webkit-scrollbar-track,
    &::-webkit-scrollbar-thumb {
      visibility: visible;
    }
  }
}

And in HTML, simply add class="overflow-auto"

<div class="overflow-auto">...</div>
-1

This will help you to overcome overflow: overlay issues as well.

.div{
      height: 300px;
      overflow: auto;
      visibility: hidden;
    }

.div-content,
.div:hover {
  visibility: visible;
}
Kashif
  • 480
  • 4
  • 11