Share via


Hiding Vertical Scrollbars with Pure CSS in Chrome, IE (6+), Firefox, Opera, and Safari

I just spent the past day trying to figure out the best way to hide scrollbars using pure CSS in the latest versions of every browser.  I wanted to be able to still scroll within the element, however, so using:

 .element { overflow: hidden; }

 was not an option.  I looked at how Facebook hides their scrollbars in the chat window, I looked at recommendations made on StackOverflow, and I invented a lot of solutions on my own.  Eventually, I arrived at a solution that I like.

 

So first, a little background... my preliminary research revealed the following:

  • There is a CSS rule that can hide scrollbars in Webkit-based browsers (Chrome and Safari).  That rule is: 

     .element::-webkit-scrollbar { width: 0 !important }
    
  • There is a CSS rule that can hide scrollbars in IE 10+.  That rule is: 

     .element { -ms-overflow-style: none; }
    
  • There used to be a CSS rule that could hide scrollbars in Firefox, but it has since been deprecated.  That rule was: 

     .element { overflow: -moz-scrollbars-none; }
    

 

The StackOverflow-recommended approach was to give my element scrollbars, wrap it in a

containing element, and make the containing element element smaller, and give it:

 overflow: hidden;

 

This is the approach Facebook uses for their chat window. However, there are two problems with

this approach:

  1. We have to hard-code in the width of a scrollbar, but this width can vary from browser to browser
  2. In Webkit browsers like Chrome and Safari, if we highlight text and drag to the right, it scrolls the inner element to the left and the scrollbars are revealed

See this screenshot from Facebook, after I clicked and dragged to the right:

 

I searched StackOverflow to see if there were any fixes to the clicking and dragging issue.  I found a JavaScript solution that seemed to work, but it was kind of hacky.  Essentially, you bind to the scroll event for your element and set the scrollLeft to 0 every time the scroll event fires.  That seems to work, but if the browser lags at all, it can look glitchy.  I continued searching for a better solution.

One solution I found recommended setting:

 .element:active { pointer-events: none; }

That prevented Webkit users from scrolling to the right when clicking and dragging to the right on text, but it also prevented them from scrolling down when clicking and dragging down on the text.  Clearly that wouldn't be a good solution.

 

Then I thought: what if instead of covering the scrollbars with a containing element, I used an ::after element to just put a white box overtop of the scrollbar?  That seemed to work, but it required that I knew how wide the scrollbar was.  After a little tweaking, I found a way to create an element that was just as wide as a scrollbar and covered the existing scrollbar.  Essentially, what I did was create an element that was nothing but a vertical scrollbar.  Then I put an ::after element on that that covered it with a solid color.  Finally, I moved the whole piece overtop of the existing scrollbar.  This method was pretty simple, but it still left a lot to be desired.  What if I didn't want the extra white space to the right of my scrollable element?  I continued searching for a better solution...

 

Next, I tried to see if there would be some hacky way to hide scrollbars in Firefox.  I could already hide them in Chrome, Safari, and IE, so Firefox was the last remaining puzzle piece.  I stumbled upon the -moz-appearance CSS property and tried a number of options.  One thing that almost worked was:

 .element { -moz-appearance: menuimage; }

This removed the scrollbars from the element, but unfortunately, it also restricted the width and height of my element.  I couldn't find any way to change the size.  After many hours, I gave up on hiding scrollbars in Firefox.

 

Then another idea came to mind.  What if the used the transform property of CSS to mess with the scrollbars somehow?  The transform property affects everything in the element, including the scrollbars!  I decided that the scale option would be my best bet.  What I ended up doing was scaling the x axis of the scrollbar element by a factor of about 0.001.  This made the scrollbar so thin that it disappeared.  Then, I wrapped the text content in another element and scaled the x axis of that element by a factor of 1000.  That seemed to work!  However, text highlighting was glitchy in Firefox with this approach.

 

I then thought of another idea that involved using transform.  What if I mirrored the element with the scrollbar, and then mirrored the text inside?  That would put the scrollbar on the left instead of the right.  I did that, and then I gave the element with the scrollbar a negative margin of 17px (the width of my scrollbar).  The scrollbar disappeared since it went outside the region of the containing element (which had overflow: hidden;).  As an added bonus, when I highlighted text in Webkit and dragged to the left, the scrollbar didn't scroll into view!  Unfortunately, this solution required me to know exactly how wide the scrollbar was.  I was looking for a solution that didn't require me to hardcode the width of the scrollbar.

 

Then, I found that I could set position: absolute; and right: 0; and it would move the scrollbar out of view without having to know the width.  That solution worked well in all browsers but IE.  For some reason, when the scrollbar gets reversed, IE removes the margin between the text and the scrollbar.  What ended up happening was that the left side of the text was getting chopped off.  So then I added a Webkit-specific rule to reverse the scrollbars only when the user was using a Webkit browser.  This solution worked in all browsers and can be seen here.

 

But then I got to thinking... wait a minute, why not just hide the scrollbar for Webkit browsers and use the overflow: hidden; solution for all other browsers?  But of course!  How simple!   I did make some changes to the original overflow: hidden; solution, however.  I set the desired width on both the element that contains the text and the outermost container.  Then I set position: absolute; and left: 0; on the text element so that the scrollbar would be out of view.  This approach doesn't need to know the width of the scrollbar ahead of time in order to work.  That solution works for all browsers too, and can be seen here.

 

And here is the full code:

HTML

 <div class="outer-container">
 <div class="inner-container">
 <div class="element">
 Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 Integer vehicula quam nibh, eu tristique tellus dignissim
 quis. Integer condimentum ultrices elit ut mattis.
 Praesent rhoncus tortor metus, nec pellentesque enim
 mattis nec. Nulla vitae turpis ut dui consectetur
 pellentesque quis vel est. Curabitur rutrum, mauris ut
 mollis lobortis, sem est congue lectus, ut sodales nunc
 leo a libero. Cras quis sapien in mi fringilla tempus
 condimentum quis velit. Aliquam id aliquam arcu. Morbi
 tristique aliquam rutrum. Duis tincidunt, orci suscipit
 cursus molestie, purus nisi pharetra dui, tempor
 dignissim felis turpis in mi. Vivamus ullamcorper arcu
 sit amet mauris egestas egestas. Vestibulum turpis neque,
 condimentum a tincidunt quis, molestie vel justo. Sed
 molestie nunc dapibus arcu feugiat, ut sollicitudin metus
 sagittis. Aliquam a volutpat sem. Quisque id magna
 ultrices, lobortis dui eget, pretium libero. Curabitur
 aliquam in ante eu ultricies.
 
 Quisque vitae tincidunt purus. Vivamus feugiat bibendum
 erat, nec interdum urna porta sed. Nunc lobortis neque
 orci, ut suscipit nisl congue feugiat. Vivamus feugiat
 tellus quis cursus sollicitudin. Curabitur dolor massa,
 dictum ut ipsum in, porttitor pellentesque ante. Aenean
 egestas cursus tempor. Maecenas semper tortor sit amet
 egestas cursus. Mauris porttitor quis nisi ut tincidunt.
 Curabitur adipiscing eleifend nibh. Praesent mauris leo,
 consequat vitae orci eget, vestibulum bibendum nisi.
 Aliquam tempus diam ut tortor cursus, eget sodales augue
 adipiscing. Nulla at dignissim libero.
 </div>
 </div>
 </div>

 

CSS

 .element, .outer-container {
 width: 200px;
 height: 200px;
}
 
.outer-container {
 border: 5px solid purple;
 position: relative;
 overflow: hidden;
}
 
.inner-container {
 position: absolute;
 left: 0;
 overflow-x: hidden;
 overflow-y: scroll;
}
 
.inner-container::-webkit-scrollbar {
 display: none;
}
 

 

I hope this helps someone!  Enjoy :)

Comments

  • Anonymous
    February 26, 2014
    excellent! still I don't understand why other browsers don't support hiding scrollbars in times of touch screens!

  • Anonymous
    March 22, 2014
    really really good

  • Anonymous
    March 27, 2014
    This does not seem to work with ie 8. Is this a fact or a problem with my code

  • Anonymous
    April 01, 2014
    Firefox 28 on Mac OS still shows the vertical scrollbar.

  • Anonymous
    April 05, 2014
    Obrigado!

  • Anonymous
    April 11, 2014
    Amazing

  • Anonymous
    May 10, 2014
    It worked by the book!!! Thank you so much John.

  • Anonymous
    June 08, 2014
    This works perfectly with everything but Firefox (29.0.1)! I've been looking for this solution for hours. Thanks John! Checkout www.wegopheryou.com using FireFox and you'll see it's not working with that. Maybe another workaround for FireFox?

  • Anonymous
    June 20, 2014
    @martin you shouldn't use hidden scrollbars it if they don't work on ie8.

  • Anonymous
    June 24, 2014
    Excellent write up. I like how you outlined the process, including attempts that didn't work out.

  • Anonymous
    July 01, 2014
    Muchas gracias saludos desde Costa Rica, viva la sele!!

  • Anonymous
    July 02, 2014
    Thank you! You saved me several hours of work. In my case the "outer-container"  in in a container fixed to the page and its width is a percentage. In this case I found that I did not need to set the width of these containers except on the element container where I added 101% to hide the scrollbar. I also had issues with the inner container collapsing and had to add a height to it (same as outer-container and element)

  • Anonymous
    September 28, 2014
    I can't find a reason to include left: 0.

  • Anonymous
    October 01, 2014
    Excellent Thank you :)

  • Anonymous
    October 21, 2014
    Hi! I just wonder, what if my div height is responsive. I mean it depends on the screen and I assigned it like: height: calc(100% - 120px); The scroll bar won't function. How do I solve this?

  • Anonymous
    October 21, 2014
    Thanks John !!! works great here :-)

  • Anonymous
    November 02, 2014
    This still seems to work even in the newest firefox. I am a developer of css styles and I've never seen this really changed. I've always been able to use:

  • { overflow: -moz-scrollbars-none !important; } To hide the scollbars, but still allow scrolling As far as I know, the only problem with it, is in linux, you cannot use your scroll wheel when there is no scroll bar, which is ok for me because I use the middle button to go into scroll mode -- however -- this may annoy others which makes it a broken "feature". at least for the linux versions I've used.  I have used this in windows however with no problems.

  • Anonymous
    November 06, 2014
    @Martin I just tested it in IE8 and it worked.

  • Anonymous
    November 06, 2014
    @-moz-scrollbars-none If you go to developer.mozilla.org/.../overflow and look at the Mozilla Extensions section, it says that "-moz-scrollbars-none" is "an obsolete API and is no longer guaranteed to work."  Better to go with an approach that is more stable.

  • Anonymous
    December 28, 2014
    nice

  • Anonymous
    January 06, 2015
    As someone already said, still showing scrollbars in Firefox on Mac

  • Anonymous
    January 07, 2015
    You are a genius sir. Your great article helped me so much!

  • Anonymous
    January 11, 2015
    I've done more research into browser support in a post on Stack Overflow at stackoverflow.com/.../26087052 .

  • Anonymous
    January 22, 2015
    how to make the horizontal scroll bar visible to scroll to the right

  • Anonymous
    January 28, 2015
    Thank u..very nice.

  • Anonymous
    January 30, 2015
    The comment has been removed

  • Anonymous
    February 14, 2015
    Doesn't work for with:100%, does it?

  • Anonymous
    March 04, 2015
    please provide a solution for scroll design on all browsers

  • Anonymous
    March 22, 2015
    As @Tom said, doesn't appear to work when width is set to 100% vs. fixed pixel dimension. Scroll bar still shows.

  • Anonymous
    May 01, 2015
    For IE 10+ I added the '-ms-overflow-style' property as in: .inner-container { position: absolute; left: 0; overflow-x: hidden; overflow-y: scroll; -ms-overflow-style: none; }

  • Anonymous
    May 19, 2015
    Amazing! I really appreciate it!

  • Anonymous
    June 04, 2015
    What If I want to scroll the content using mouse scroll? Is there any way to do this?

  • Anonymous
    June 05, 2015
    not work with Opera ,what the css for it?

  • Anonymous
    July 17, 2015
    Works so well! I can finally go to sleep now. MUCH GRATITUDE!!!

  • Anonymous
    September 20, 2015
    awesome job