---
title: Adding Flutter to any web application
short-title: Add Flutter to any web app
description: Learn the different ways to embed Flutter views into web content.
---
Flutter views and web content can be composed to produce a web application
in different ways. Choose one of the following depending on your use-case:
* A Flutter view controls the full page ([full page mode][])
* Adding Flutter views to an existing web application ([embedded mode][])
[full page mode]: #full-page-mode
[embedded mode]: #embedded-mode
## Full page mode
In full page mode, the Flutter web application takes control of the whole
browser window and covers its viewport completely when rendering.
This is the default embedding mode for new Flutter web projects, and no
additional configuration is needed.
```html highlightLines=6
```
When Flutter web is launched without referencing `multiViewEnabled` or a
`hostElement`, it uses full page mode.
To learn more about the `flutter_bootstrap.js` file,
check out [Customize app initialization][].
[Customize app initialization]: {{site.docs}}/platform-integration/web/initialization/
### `iframe` embedding
Full page mode is recommended when embedding a Flutter web application through an
`iframe`. The page that embeds the `iframe` can size and position it as needed,
and Flutter will fill it completely.
```html
```
To learn more about the pros and cons of an `iframe`,
check out the [Inline Frame element][] docs on MDN.
[Inline Frame element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe
## Embedded mode
Flutter web applications can also render content into an arbitrary number of
elements (commonly `div`s) of another web application; this is called "embedded
mode" (or "multi-view").
In this mode:
* A Flutter web application can launch, but doesn't render until the first
"view" is added, with `addView`.
* The host application can add or remove views from the embedded Flutter web
application.
* The Flutter application is notified when views are added or removed,
so it can adjust its widgets accordingly.
### Enable multi-view mode
Enable multi-view mode setting `multiViewEnabled: true` in the
`initializeEngine` method as shown:
```js highlightLines=8 title="flutter_bootstrap.js"
{% raw %}{{flutter_js}}{% endraw %}
{% raw %}{{flutter_build_config}}{% endraw %}
_flutter.loader.load({
onEntrypointLoaded: async function onEntrypointLoaded(engineInitializer) {
let engine = await engineInitializer.initializeEngine({
multiViewEnabled: true, // Enables embedded mode.
});
let app = await engine.runApp();
// Make this `app` object available to your JS app.
}
});
```
### Manage Flutter views from JS
To add or remove views, use the `app` object returned by the `runApp` method:
```js highlightLines=2-4,7
// Adding a view...
let viewId = app.addView({
hostElement: document.querySelector('#some-element'),
});
// Removing viewId...
let viewConfig = app.removeView(viewId);
```
### Handling view changes from Dart
View additions and removals are surfaced to Flutter through the
[`didChangeMetrics` method][] of the `WidgetsBinding` class.
The complete list of views attached to your Flutter app is available
through the `WidgetsBinding.instance.platformDispatcher.views` iterable. These
views are of [type `FlutterView`][].
To render content into each `FlutterView`, your Flutter app needs to create a
[`View` widget][]. `View` widgets can be grouped together under a
[`ViewCollection` widget][].
The following example, from the _Multi View Playground_, encapsulates
the above in a `MultiViewApp` widget that can be used as the root widget for
your app. A [`WidgetBuilder` function][] runs for each `FlutterView`:
```dart highlightLines=25,39,46-49,56-61,72 title="multi_view_app.dart"
import 'dart:ui' show FlutterView;
import 'package:flutter/widgets.dart';
/// Calls [viewBuilder] for every view added to the app to obtain the widget to
/// render into that view. The current view can be looked up with [View.of].
class MultiViewApp extends StatefulWidget {
const MultiViewApp({super.key, required this.viewBuilder});
final WidgetBuilder viewBuilder;
@override
State createState() => _MultiViewAppState();
}
class _MultiViewAppState extends State with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_updateViews();
}
@override
void didUpdateWidget(MultiViewApp oldWidget) {
super.didUpdateWidget(oldWidget);
// Need to re-evaluate the viewBuilder callback for all views.
_views.clear();
_updateViews();
}
@override
void didChangeMetrics() {
_updateViews();
}
Map