WebView Hell in Flutter

Video thumbnail

I want to share a slightly more personal reflection on my work and what I consider the nightmare of WebViews in Flutter, just as I explained to you the nightmare of integrating a payment gateway like PayPal in Flutter.

Something that seems so simple, or at least I perceive it from that perspective (without having created a browser, of course), is the ability to interpret HTML. We all start our journey in software development, or at least most of us, by creating a "Hello World" with HTML. From there, we move on to JavaScript, CSS, and then to more robust programming languages (PHP, Python, Node). For this reason, my view is that the HTML, CSS, and JavaScript layer should always be straightforward to handle.

When we try to use this content in mobile applications—as is the case with Desarrollo Libre, an application I developed in Flutter and continue to improve—its core is precisely HTML, because the source is a web page. Obviously, I want to take advantage of that content so users can view it easily.

We all start programming with HTML. It's not a "real" language, but hey, it gets you building things fast. That's why, when I wanted to use HTML inside my Flutter app, I thought it was going to be just as easy.

In fact, the core of my DesarrolloLibre app is HTML, and the logic is simple:
if I already have my HTML content, why not use it inside the Flutter app too?

Well... yes, it sounds logical, but it doesn't work that way.

The Problem of Cross-Platform Rendering

The detail is that the implementation is strange and uneven. Notice that here on Mac (where I'm working now), I always find weird structures, as you can see.

While on Windows, Android, and even iOS (although I haven't launched the application yet), the HTML content is rendered acceptably (saving the issue of CSS styles, which is another matter), on Mac I have structural problems. I'm going to a page I'm working on so you can see the result: it looks decent here, with its CSS, and I'm directly placing the HTML.

❓ Why Don't Google and Flutter Create a Native API?

The real horror is that working with the Webview is a nightmare, and I don't understand why the people at Google or Flutter don't implement a good Webview that's part of the standard API.

I don't think it's such a complicated operation. A native Webview already exists on Android and I think on iOS too. Therefore, I don't know why they don't use or create an internal API that consumes that native Webview from each of the operating systems. I haven't developed native applications on Windows and macOS yet, but I use Flutter, but I'm sure a solution must exist. This is what seems extremely strange to me.

The reality: each platform does what it wants

On Android it appeared with styles.
On Windows it looked more or less okay.
On macOS... well, there it looked like a completely different page.

And that was with the same HTML.

That's when I understood that Flutter doesn't have a standard WebView and that each plugin does what it can with its platform.

The Endless Search for Packages (pub)

As you can imagine, to implement this functionality, we use an extension or a package from .pub. This is a bit like using Flask, where you install the base and then start installing packages and plugins to nourish the project.

Yes, we install the package, but the result is quite horrible. I'm going crazy looking for a functional Webview for Mac, and it has actually been very difficult for me to find it.

Many Webview Packages for Flutter

I've found several Webviews available on the web. On a page I recently found, where I'm researching, we have several:

https://fluttergems.dev/webview/

But look how strange the matter is or what seems strange to me; this one is for Android and iOS. I used these in the DesarrolloLibre project:

  webview_flutter: 4.7.0
  webview_windows:
  desktop_webview_window:
  # webview_all:

Others gave me errors and others, others say they work for Mac and have not been tested; what I want to note here is that we have many and several do not work as expected.

It's funny because there's one that says it's open for all platforms but hasn't tested it on MacOS

I tried others and they gave an error when executing the app or installing them.

But what I mean is that it becomes a nightmare in that sense because there isn't one that's standardized

webview_flutter: official, but far from perfect

The official plugin works, yes... but:

  • It's not 100% on the Android/iOS level.
  • For macOS and Windows, it's another story.
  • And for HTML as a string, forget about it if you want consistency.

In my case, I ended up enabling JavaScript, controlling the WebView with a WebViewController, and even then, some functions didn't work the same across platforms.

Alternative plugins: webview_windows, desktop_webview_window, and company

This is when I entered the dark world of plugins:

webview_flutter: 4.7.0
webview_windows:
desktop_webview_window:
# webview_all:

Some:

  • installed but gave an error on execution,
  • others said “works on macOS” but hadn't tested it,
  • others directly didn't render embedded HTML.

One even claimed to support all platforms, but had the label “not tested.” Literally.

The chaos of cross-platform support (and those who say “macOS supported” without testing it)

When a plugin puts “macOS support” but then clarifies “no testing,” what it really means is:

“Nobody tested anything here. Good luck if it works.”

And yes, I found out the hard way.

Variable HTML Content and the WebView Challenge

Another problem I find with WebViews is the difficulty in handling variable HTML content. Often, I have HTML code that I want to inject, and many plugins simply don't display it, don't handle it well, or the result is confusing.

Most WebViews focus on rendering content from a full URL, which is very different from rendering a pure and simple HTML code fragment. From a native web application (where everything is HTML), this task is trivial. However, in an environment like Flutter, where we depend on so many plugins and ways to interpret HTML content, it becomes a real nightmare.

Using a Consistent WebView on All Platforms: An Impossible Task

With all that has been expressed, it is understandable why I titled my publication this way: Something as simple as the need to use HTML content in a Flutter app, either by supplying a URL or direct HTML code, becomes an extremely complex task across different operating systems.

The current plugins:

  • Do not work on all platforms (or present bugs on specific ones).
  • Only accept a URL and fail with direct HTML content.
  • Include warnings in their documentation, such as "it's in beta" or "not tested" (No Testing), even though the platform is listed as available.

Rendering differences between Android, Windows, and macOS

On macOS in particular, the HTML looked like a different page.
On Windows it did work, but sometimes it ignored the CSS.
On Android... well, there I was at least able to make progress.

Plugins that fail to install or execute

It happened to me several times: you install, you run... error from startup.
Or warnings like “this package is in beta.”
Or literally nothing works.

The absolute void of official documentation

There is no official guide for:

  • Embedded HTML
  • Internal CSS
  • Windows/macOS compatibility
  • Performance
  • Multi-screen WebViews

You literally have to guess.

The Lack of Documentation and Consistency

If a package claims to be available for macOS, but then indicates "No Testing" right next to it, what are we supposed to understand? I interpret that the package has never been tested on Mac, and if the developers themselves haven't tested it, I don't understand how they list it as an option. Apart from this inconsistency, the official documentation for most of these pubs is, essentially, non-existent.

How I chose a “sufficiently functional” WebView for each platform

Android: relatively stable

The official one works. JavaScript works. HTML string... it depends, but it's viable.

iOS: permissions and previews

You have to enable the embedded view in Info.plist, otherwise it won't even start.

Windows: limited options

Here plugins like webview_windows help, but don't expect miracles.

macOS: the platform where almost nothing works as it should

Here I can say that the plugins that “worked” always had an asterisk:

  • it doesn't support HTML string
  • it doesn't execute scripts
  • it fails to open CSS
  • or it simply doesn't render

My final solution: cross-platform code with conditionals

After many tests, this is what I ended up doing:

if (Platform.isAndroid) {
 // un plugin
}
else if (Platform.isWindows) {
 // otro plugin
}
else if (Platform.isMacOS) {
 // solución alternativa
}

Conclusion: A Custom, Personalized Development

I wanted to share my perspective on all this so that you can draw your own conclusions when planning your development.

In the Desarrollo Libre project, I need to use HTML both at the link level and as injectable HTML code. In the end, to simply reliably render HTML content, I had to resort to extensive and personalized development, creating my own methods with multiple conditionals that return the result based on the platform used and the WebView supported in that specific environment.

if(Platform.isAndroid){ }

My general recommendation:

  • Android/iOS → webview_flutter (with extra work).
  • Windows → webview_windows.
  • macOS → only use WebView if it's essential; otherwise, look for alternatives.
  • HTML as a string → test before committing to a plugin.
  • Complex widgets like TradingView → only work on certain platforms.

If you expect that “loading HTML in Flutter” will be as easy as it sounds…
Be prepared: it's possible, but you'll be writing conditional code like you live in 2010.

❓ Frequently Asked Questions

  • How to load HTML as a string in Flutter?
    • With loadHtmlString (when the plugin supports it). Not all of them do.
  • Which plugin to use for Windows or macOS?
    • Windows: webview_windows.
      macOS: very few work well. You have to test case by case.
  • How to make WebView support JavaScript?
    • With: javascriptMode: JavascriptMode.unrestricted

However, in this article I will show you a better solution: converting HTML text to widgets.

I want to share a slightly more personal reflection on my work and what I consider the nightmare of WebViews in Flutter, just as I explained to you the nightmare of integrating a payment gateway like PayPal in Flutter.

I agree to receive announcements of interest about this Blog.

I'll talk about the problems I've had when trying to display HTML content via a URL or code on different platforms in Flutter.

| 👤 Andrés Cruz

🇪🇸 En español