adaptive_svg 0.5.0
adaptive_svg: ^0.5.0 copied to clipboard
Platform-adaptive SVG rendering. DOM <svg> on web, flutter_svg on native.
adaptive_svg #
Platform-adaptive SVG rendering for Flutter. Uses the browser's native <svg> element on web, and flutter_svg on all other platforms.
Why? #
flutter_svg renders SVGs by parsing them into Flutter Path objects via Skia/Impeller. This works well for simple icons, but silently drops many SVG features:
| Feature | Browser DOM | flutter_svg |
|---|---|---|
| Filters (blur, shadow, color matrix) | Yes | No |
CSS animations / @keyframes |
Yes | No |
SMIL <animate> / <animateTransform> |
Yes | No |
<style> block with class selectors |
Yes | Partial |
:hover, :focus pseudo-classes |
Yes | No |
<foreignObject> (HTML in SVG) |
Yes | No |
Nested <svg> elements |
Yes | No |
External image URLs in <image> |
Yes | No (data URI only) |
letter-spacing / word-spacing |
Yes | No |
| Complex masks with gradients | Yes | Partial |
adaptive_svg gives you full SVG spec coverage on web by delegating to the DOM, while keeping flutter_svg for native where it works well.
Install #
dependencies:
adaptive_svg: ^0.3.0
Usage #
import 'package:adaptive_svg/adaptive_svg.dart';
// From a string
AdaptiveSvg(svgMarkup, width: 48, height: 48)
// From an asset
AdaptiveSvg.asset('assets/icon.svg', width: 24, height: 24)
On web, both render inline <svg> elements in the DOM. On iOS, Android, macOS, Windows, and Linux, they delegate to SvgPicture.string / SvgPicture.asset from flutter_svg.
Gesture handling #
On web, the SVG is rendered inside an HtmlElementView. Platform views punch a hole in Flutter's glass pane, so ancestor GestureDetector / InkWell widgets do not receive taps on the SVG region.
Set gestures: true and pass the callbacks you need — the widget stacks a PointerInterceptor + GestureDetector overlay on web (and just wraps with GestureDetector on native):
AdaptiveSvg(
svgMarkup,
gestures: true,
onTap: () => print('tapped'),
onLongPress: () => print('long press'),
onHover: (hovering) => print('hover: $hovering'),
)
When gestures: false (default) no gesture widgets are built — the rendered tree is just the bare SVG with zero overhead.
Rounded corners #
AdaptiveSvg(
svgMarkup,
width: 200,
height: 120,
borderRadius: BorderRadius.circular(16),
)
On native, the rendered SVG is wrapped in a ClipRRect. On web, CSS border-radius + overflow: hidden is applied to the wrapper <div> that hosts the platform view — Flutter's ClipRRect doesn't reliably clip HtmlElementView content, so the rounding is baked into the DOM container directly.
Web-only options #
// Disable pointer events (useful for static thumbnails in a GestureDetector)
AdaptiveSvg(svgMarkup, interactive: false)
// Enable CORS for external <image> elements
AdaptiveSvg(svgMarkup, imageCrossOrigin: CrossOrigin.anonymous)
Example #
The example/ app renders 25+ SVG test cases side-by-side (AdaptiveSvg vs flutter_svg) across 15 categories. Run it on web to see the differences:
cd example
flutter run -d chrome
License #
MIT