Pure CSS Scroll Shadows (Vertical + Horizontal)

A long time ago (2012!), Lea Verou shared a way on how to add scrolling shadows to containers that needs scrolling. Using those shadows in a scroll container is a great UX thing, as they visually tell the user that the content is scrollable.

Her code however, only worked with containers that scroll vertically. Based upon Lea’s code I created a version that also plays nice with horizontal scroll containers.

Whilst I was at it, I also introduced CSS Custom Properties, as they allow easy theming. Using the “CSS Variables” --background-color, --shadow-color, and --shadow-size you can configure the result.

Hope you like it 🙂

# 🐛🍏 A note on MobileSafari (iOS)

Update 2022.07.05: The workaround listed below was necessary for iOS versions predating iOS 15. The fix is no longer needed as of iOS 15.4. Versions 15.0 – 15.4 had a regression that prevented this fix from working, so those specific versions do not support pure CSS Scroll Shadows.

Out of the box this technique unfortunately does not play that nice on iOS: MobileSafari does not seem to re-render the backgrounds during scroll. I did notice however that it will correctly re-render after manually zooming in and out on the page. This is detailed in Webkit Bug 181048.

In said bug report a solution to the problem is mentioned:

I’ve discovered that updating a CSS variable on a -webkit-overflow-scrolling: touch; element when it’s scrolled causes it to repaint correctly.

With a little bit of JavaScript we can trigger exactly this:

// Fix for Mobile Safari that doesn't correctly re-render backgrounds during scroll
// @ref https://bugs.webkit.org/show_bug.cgi?id=181048
if (CSS.supports("-webkit-overflow-scrolling: touch")) {
  document.querySelectorAll(".scrollcontainer").forEach((scroller) => {
    scroller.addEventListener("scroll", () => {
      scroller.style.setProperty("--force-paint", Date.now());
    });
  });
}

It’s also possible to force repaints by attaching an animation to the .scrollcontainer. Even a dummy (empty) animation will do.

/*Fix for Mobile Safari that doesn't correctly re-render backgrounds during scroll */
@supports (-webkit-overflow-scrolling: touch) {
  @keyframes dummy {
  }
  .scrollcontainer {
    animation: 1s dummy linear infinite;
  }
}
Did this help you out? Like what you see?
Thank me with a coffee.

I don\'t do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

BuymeaCoffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Unless noted otherwise, the contents of this post are licensed under the Creative Commons Attribution 4.0 License and code samples are licensed under the MIT License

Join the Conversation

5 Comments

  1. How do you prevent the scrollbars from overlapping the shadows? I have tried every property I can think of, even some experimental ones. Am I missing something simple?

Leave a comment

Leave a Reply to can Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.