I use flutter_svg on my flutter project, and i have a function which return the SvgPicture Widget
with a specific color:
static Widget icon({double? width, double? height, Color? color}) {
return SvgPicture.asset(
'assets/icon.svg',
width: width,
height: height,
colorFilter:
color != null ? ColorFilter.mode(color, BlendMode.srcIn) : null,
);
}
It works great on other platforms but only on Iphone - Safari browser, when rendering with html, the color option does not work. The issue is not with flutter, package or html. The Safari does not support the color filter as mentioned here.
How to make it work?
Edit
This issue appears to be on Android - Firefox too.
I use flutter_svg on my flutter project, and i have a function which return the SvgPicture Widget
with a specific color:
static Widget icon({double? width, double? height, Color? color}) {
return SvgPicture.asset(
'assets/icon.svg',
width: width,
height: height,
colorFilter:
color != null ? ColorFilter.mode(color, BlendMode.srcIn) : null,
);
}
It works great on other platforms but only on Iphone - Safari browser, when rendering with html, the color option does not work. The issue is not with flutter, package or html. The Safari does not support the color filter as mentioned here.
How to make it work?
Edit
This issue appears to be on Android - Firefox too.
Share Improve this question edited Mar 20 at 7:28 VLAZ 29.1k9 gold badges63 silver badges84 bronze badges asked Mar 17 at 20:25 MahseinMahsein 1729 bronze badges1 Answer
Reset to default 0Solutions
CanvasKit
use CanvasKit for rendering web: flutter build web --web-renderer canvaskit
SvgPicture.string()
instead of using SvgPicture.asset()
, load the svg as text, change the color, use SvgPicture.string()
. but I suggest doing it only on Iphone - Safari. here is how:
import 'package:flutter/foundation.dart';
import 'dart:html' as html;
bool get isIosSafari {
if (!kIsWeb) return false;
final ua = html.window.navigator.userAgent.toLowerCase();
final isIos = ua.contains('iphone') || ua.contains('ipad') || ua.contains('ipod');
// Ensure it's Safari and not another browser on iOS (like Chrome or Firefox)
final isSafari = ua.contains('safari') && !ua.contains('crios') && !ua.contains('fxios');
return isIos && isSafari;
}
static Widget icon({double? width, double? height, Color? color}) {
if (isIosSafari && color != null) {
return FutureBuilder<String>(
future: rootBundle.loadString('assets/icon.svg'),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
String svgStr = snapshot.data!;
final hexColor =
'#${color.value.toRadixString(16).padLeft(8, '0').substring(2)}';
svgStr = svgStr.replaceAll(RegExp(r'fill="[^"]*"'), 'fill="$hexColor"');
return SvgPicture.string(svgStr, width: width, height: height);
}
// return empty box until ready
return SizedBox(width: width, height: height);
},
);
} else {
return SvgPicture.asset(
'assets/icon.svg',
width: width,
height: height,
colorFilter: color != null ? ColorFilter.mode(color, BlendMode.srcIn) : null,
);
}
}
Edit
solution for Android - Firefox is the same (but obviously the isIosSafari
part is going to change).