Styling scrollbars with CSS

Styling scrollbars with CSS

Even if this topic has already been discussed in details elsewhere, I'd like to share a few discoveries about my recent experiment with custom scrollbars.

The current state is not great

So here is the deal: while you can do really funky things in webkit, it will not be working in Firefox because it supports only two properties:

  • scrollbar-width
  • scrollbar-color

So except if you have full control over which browser your visitor will be using (or if you are happy to provide a different experience for your visitors, but I'm not sure what your designer will think about that), you only have a limited set of option.

In terms of width, you will probably go with "thin" which removes the scroll buttons that nobody uses anyway and get a scrollbar that has a width of about 8px.

scrollbar-width: thin;
/* Yep, that's the only line you need to know */

In my opinion, it's better to stick with simple, minimalist scrollbars that are consistent for Chrome and Firefox.

Color is not always that easy

In Firefox, when you set a color for your scrollbar, it will automatically be tinted with a tinted variant on hover (a lighter one for dark colors and a darker one for light colors). This is not the case in Chrome, so you have to define hover yourself. This can be done this way for example:

.scroller {
  --scroller-color: 0, 0%;
  --scroller-color-lightness: 80%;
  --scroller-hover-factor: 0.8;
  --scroller-thumb: hsl(var(--scroller-color), var(--scroller-color-lightness));
  /* Replicate hover for webkit */
  --scroller-thumb-hover: hsl(
    var(--scroller-color),
    calc(var(--scroller-color-lightness) * var(--scroller-hover-factor))
  );
  --scroller-background: transparent;
  scrollbar-color: var(--scroller-thumb) var(--scroller-background);
  scrollbar-width: thin;
}
.scroller::-webkit-scrollbar {
  width: 8px;
}
.scroller::-webkit-scrollbar-track {
  background: transparent;
}
.scroller::-webkit-scrollbar-thumb {
  background: var(--scroller-thumb);
}
.scroller::-webkit-scrollbar-thumb:hover {
  background: var(--scroller-thumb-hover);
}

The issue with border-radius and scrollbars

So it's easy enough to get nice looking boxes without using JS libraries but then, suddenly, you have a border-radius to your boxes and tadaa... it's not looking great, at all.

There are a couple of solutions:

Using a clip-path:

.round-box {
  clip-path: inset(0% 0% 0% 0% round 1em);
}

Or maybe go a bit crazy and use pseudo-elements if you don't like to see your beautiful scrollbar clipped in a strange way:

.round-box-holder {
  border-radius: 1em;
  contain: content;
  position:relative;
  width:fit-content;
}
.round-box-holder:before, .round-box-holder:after {
  position:absolute;
  top:0;
  right:-8px;
  content:"";
  width:1em; /* should match padding l/r */
  height:1em; /* should match padding t/b */
  background:#fff;
  z-index:2;
}
.round-box-holder:after {
  top: auto;
  bottom:0;
}

Almost works but out of alignement for Safari.

A demo

If you want to play around, you can check the demo below