Recently it was discovered that the cause of this issue was WebGL 2.0 on Safari/WebKit (Source). This issue should be resolved if you are currently running Flutter 2.7 in the stable channel.
Each source link in this answer leads you to the actual comments and respective authors of these workarounds at https://github.com/flutter/flutter/issues/89655
Best Solution
Since disabling WebGL 2.0 through Safari's Experimental Features will only affect your own computer AND switching to the master channel is not a viable solution for apps in production, you'll need to tell the browser that Flutter's engine does not support WebGL 2.0 on Safari (Source). This snippet of code needs to be called in the head tag before your main.dart.js is called in the index.html file.
<!-- Apple WebGL 2.0 fix (https://github.com/flutter/flutter/issues/89655#issuecomment-919685843) -->
<!-- TODO: Remove when https://github.com/flutter/engine/pull/29038 is merged to stable -->
<script src="https://unpkg.com/platform@1.3.5/platform.js"></script>
<script type="text/javascript">
let isSafari = /^((?!chrome|android).)*safari/i.test(platform.ua);
if (isSafari) {
HTMLCanvasElement.prototype.getContext = function (orig) {
return function (type) {
return type !== "webgl2" ? orig.apply(this, arguments) : null
}
}(HTMLCanvasElement.prototype.getContext)
}
</script>
TextStyle Workaround
The previously proposed solution to this issue was to set a slightly transparent underline for all text in your app by using the DefaultTextStyle widget. (Source)
TextStyle(
decoration: TextDecoration.underline,
decorationColor: Colors.white.withOpacity(0.01),
)
CanvasKit Workaround
If these solutions did not help, you can also try disabling CanvasKit as a last resort. (Source)
<head>
<!-- * Safari Renderer * -->
<script src="https://unpkg.com/platform@1.3.5/platform.js"></script>
<script>
if (platform.name.toLowerCase() == "safari" && parseInt(platform.version.split(".")[0]) >= 15) {
window.flutterWebRenderer = "html";
} else {
// Optional, default is `auto`
window.flutterWebRenderer = "canvaskit";
}
</script>
...
</head>
<body>
...
<!-- * Initialize Website * -->
<script src="main.dart.js" type="application/javascript"></script>
</body>
For this workaround to work you will need to set the web-renderer to auto when running or building the project in the terminal:
flutter build web --release --web-renderer auto
You might have to replace some widgets that only work nicely with the CanvasKit renderer since this workaround will force Safari 15 to use the HTML renderer:
import 'dart:js' as js;
// ** //
bool isCanvasKit() => js.context['flutterCanvasKit'] != null;
Widget dynamicText = isCanvasKit()
? Text("CanvasKit")
: Text("HTML");
If any of these solutions fixed your issue, please consider marking it as accepted.