Why a CSS shadow looks different in Flutter
Copying the numbers from a design tool or CSS into BoxShadow gives a sharper shadow than expected, because the blur is measured differently:
- CSS blurs with a Gaussian whose standard deviation (sigma) is half the blur length, so
12pxmeans sigma 6. - Flutter converts
blurRadiuswithsigma = blurRadius × 0.57735 + 0.5(Shadow.convertRadiusToSigma), soblurRadius: 12means sigma 7.43.
To match a CSS blur b, use blurRadius = (b / 2 − 0.5) / 0.57735. A 12px CSS blur becomes blurRadius: 9.53. The converter does this for you. CSS blurs under 1px have no Flutter equivalent, because Flutter's smallest non-zero sigma is 0.5; they become sharp.
Spread and rounded corners
CSS grows the corner radius of a shadow by its spread. Flutter does not: BoxDecoration inflates the shadow rectangle by spreadRadius but draws it with the box's own borderRadius. With a large spread on a rounded box, the shadow's corners are therefore tighter in Flutter. The preview here shows the Flutter result.
Material elevation shadows
The presets are Flutter's own kElevationToShadow values for elevations 1, 2, 3, 4, 6, 8, 9, 12, 16 and 24, each made of three layers. The generated code refers to kElevationToShadow[n] (from package:flutter/material.dart) instead of copying the numbers. Change any value and the code switches to explicit BoxShadow entries.
Limitations
- Inset shadows are skipped:
BoxShadowhas no inset option. - Only
pxlengths are read from CSS, and a layer without a colour is drawn black (CSS would use the text colour). - Shadows are painted under the box. If the box colour is translucent, Flutter shows the shadow through it, while CSS hides the part under the box.
For single colours, the Flutter Color converter explains the Color(0xAARRGGBB) format used in the output.
How the output was checked
Eleven cases (no blur, blurs from 4 to 30, positive and negative spread on rounded corners, two-layer shadows and Material elevations 1, 4, 8 and 24) were painted with the generated BoxDecoration on Flutter 3.47.7 and with this page's preview method in Chrome, then compared pixel by pixel: no pixel differed by more than 8 of 255 levels. CSS box-shadow with the converted blur differed by at most 12 levels, except at the corners of spread shadows (up to 27), for the reason above. The generated code passes flutter analyze with prefer_const_constructors (2026-10-30).