Matching drop shadows across CSS, Android, iOS, Figma, and Sketch
If you’ve ever tried to implement consistent shadows across multiple platforms and design tools, you may have noticed that they don’t look the same. Thankfully, it is possible to get them all to match.
The image above shows the same drop shadow values, rendered by CSS on the web, Android, and iOS. It’s a dark and extreme shadow, to make the differences more pronounced. The shadows are black, with no X offset, 24px Y offset, and a 24px blur radius. I’ve used “px” when noting the values, but when building each test app to generate the images for this article, I used the platform’s equivalent unit — dp on Android, and points on iOS.
The CSS and Android examples may look the same, but they’re slightly different. The image below demonstrates that the Android shadow is slightly blurrier. Please note that the Android shadows in this article are generated with setShadowLayer
, rather than Material elevation.
Safari vs Firefox vs Chrome #
We’ve been discussing CSS drop shadows without being specific about which CSS property, browser, and rendering engine is being used. That’s okay though — I used Safari for most of the screenshots, but box-shadow looks effectively the same across Safari, Firefox, and Chrome.
CSS vs Figma vs Sketch #
In other good news, drop shadows match across CSS, Sketch, and Figma. Please note that background blurs are a different story. We’re only comparing drop shadows in this article.
Blur is to blame #
There’s quite a few properties to describe a drop shadow. Thankfully, the position offsets and colour all behave the same across the platforms and design tools being measured. The only difference is how the blur radius is handled.
I’ve previously investigated how blurs are rendered across different design tools and CSS, but I missed something important. By re-stacking the various blur tests in a different order, a pattern emerges. There’s three distinct sizes, roughly 1×, 2× and 3× scales. The drop shadows all fall into the 1× and 2× scale factors.
Scale factors #
The CSS spec defines the blur to be a standard deviation equal to half the blur radius, which would make the 2× scaled blurs a standard deviation equal to the blur radius. That was the hint needed to figure out a precise scale for converting CSS drop shadow blurs to iOS — the iOS blur radius is twice as big, so scaling a CSS blur radius by 0.5× gets them looking the same.
The Android blur radius scale factor isn’t quite as straight forward. Android uses Skia for a lot of its rendering, and the source code mentions scaling the blur by 1 / sqrt(3) because “Safari does the same”, and that “it actually should be 1”. Those comments are quite old, and Safari has since changed to be in line with the CSS spec. That means Android’s shadows don’t match CSS, because of Safari. Wild.
Huge thanks to Kit Grose for finding the Skia code comment while reviewing a draft of this article.
Posterising the results shows how well they now line up. A perfect match is impossible, due to differences in rendering methods and code, but I do feel like this is good enough.
Here’s all the scale factors to convert to and from the various platforms and design tools.
Source and destination | Formula | Blur radius scale factor |
---|---|---|
CSS, Sketch, or Figma to Android | sqrt(3) / 2 | 0.866× |
CSS, Sketch, or Figma to iOS | 0.5× | |
Android to CSS, Sketch, or Figma | 1 / sqrt(3) × 2 | 1.155× |
Android to iOS | 1 / sqrt(3) | 0.577× |
iOS to CSS, Sketch, or Figma | 2.0× | |
iOS to Android | sqrt(3) | 1.732× |
This research was conducted so Pinwheel could include the correct scale factor when exporting Android and iOS code for shadows and shadow sets.
Published 22 March 2025.