Flutter Web: Getting started with Responsive Design
Flutter Web has been out there for quite some time, and currently, it is in the Beta stage of Flutter. But it is quite stable, and the plugin support for Flutter Web is also improving day-by-day. So if you haven’t yet got a chance to check out the Flutter Web, I believe this is the perfect time to hop on and give it a try.
In this article, I will show you how to get started with a Flutter Web project and make it responsive.
Flutter Web Architecture
Before getting started with the project, let’s take a look at the architecture of Flutter Web.
If you are not familiar with the architecture of Flutter used in mobile apps, here is an overview of it:
The architecture of Flutter for mobile apps mainly consists of the following three layers:
- Framework: This layer is purely written in Dart and consists of the core building blocks of Flutter.
- Engine: The layer below is primarily written in C/C++ and provides low-level rendering support using Google’s Skia graphics library.
- Embedder: This layer basically consists of all platform-specific dependencies.
Now, let’s take a look at the architecture of Flutter Web and how it differs from this.
Flutter Web Architecture, is depicted using just two layers:
- Framework: Consisting of pure-Dart code.
- Browser: Consisting of C++ & JavaScript code.
As you can see, the top layer ( Framework) almost contains the same type of components.
The main difference is in the Browser layer. Actually, the bottom two separate layers present in the mobile architecture is replaced with just one layer. Instead of Skia Engine (as it is not supported to run on browsers), it uses a JS Engine. Flutter Web involves compiling of Dart to JavaScript, instead of the ARM machine code that is used for mobile apps. It uses a combination of DOM, Canvas, and CSS to render Flutter components in the browser.
Getting Started
As I mentioned in the beginning, Flutter Web is currently in the beta stage. So, in order to create a Flutter app with web support, you need to be in the beta channel of Flutter.
To run and debug a Flutter Web app you will require the Chrome browser.
Follow the steps below, to create a new Flutter Web project:
- Shift to the beta channel:
flutter channel beta
2. Upgrade Flutter:
flutter upgrade
3. Enable web support:
flutter config --enable-web
4. Create a new Flutter project:
flutter create explore
Here, explore is the name of the Flutter Web app that I am going to create.
5. Open the project using your favorite IDE.
To open it using VS Code, you can use this command:
code explore
Now, if you take a look at the directory structure, you will notice that there is a folder called web.
This means your project is properly configured to run on browsers. Also, you will see that Chrome is available as one of the devices for running the Flutter app.
You will get the same Counter app as the starting project. For running it from VS Code you can use F5
, or you can use this command from the terminal:
flutter run -d chrome
The current state of affairs looks like this:
With the starter project set up, let’s start building our intended web app.
Web interface design
The web interface that we are going to create is inspired by Tubik’s example on Dribbble:
Go to lib > main.dart, and replace the whole code with the following:
Now, we have to define the HomePage
widget, which will contain the UI of the app. You will understand in a bit why I have defined it as a Stateful Widget.
You might have noticed that I have used MediaQuery
to get the size of the screen. I have done this because I will be sizing the widgets with respect to the size of the screen. This will make the widgets responsive and will prevent most of the overflow issues during resizing of the browser window.
Let’s add a top bar which will look like this:
To do so, you will need the following code:
Immediately you will notice that something wrong and it doesn’t feel like a web UI. Where’s the hover effect?
Yeah, Flutter components don’t have the hover effect by default. But I will show you the easiest way to achieve that. Just so you’d know, after adding the hover effect it will look like this:
There is a property of the InkWell()
widget called onHover
which you can use to track when the mouse pointer enters or leaves the boundary of the component.
Follow the steps below to get this effect:
- Add a List of booleans which will be used to track the hover (add as many booleans as the components you need to apply the hover effect on):
List _isHovering = [false, false, false, false];
- Update the boolean value corresponding the component, and set the Text color or any other changes that you want to show during hover, according to that boolean value :
InkWell(
onHover: (value) {
setState(() {
_isHovering[0] = value;
});
},
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Discover',
style: TextStyle(
color: _isHovering[0]
? Colors.blue[100]
: Colors.white,
),
),
SizedBox(height: 5),
// For showing an underline on hover
Visibility(
maintainAnimation: true,
maintainState: true,
maintainSize: true,
visible: _isHovering[0],
child: Container(
height: 2,
width: 20,
color: Colors.white,
),
)
],
),
),
If we add the image inside the Scaffold body
, it will start from under the top bar. But, according to the design, the image should flow below the top bar.
Achieving this design is really simple, you just have to define one property of the Scaffold called extendBodyBehindAppBar
and set it to true.
You might have also noticed that I have added a quick access bar that sits on the top of the image in the bottom-center position.
To get a UI like this, use a Stack widget inside the body
of the Scaffold.
I am just including the code for explaining the structure of the UI. The full UI code for this section is available here. You will get a link to the whole project at the end of this article.
Now, we will be adding a few more UI elements to the webpage. First of all, wrap the whole body
of the Scaffold in a SingleChildScrollView
widget to make it scrollable.
We will keep this website simple. So, let’s add just three more sections.
- Featured
- Destinations diversity
- Bottom information
Featured section
This section will contain a heading and a Row of three images with their labels. It will look like this:
UI code for the heading and its description:
The code for each image with its label is as follows:
If you try to resize the browser window now, you will find that it is already quite responsive:
Destinations diversity section
In this section, we will be adding an image carousel with a floating selector of potential destinations called “Destinations diversity”. It will look like this:
For the carousel, you can use the Flutter package called carousel_slider.
Follow the steps below to build the carousel:
- Define a List of images and the labels for them:
- Generate a list of Widgets to show in the carousel:
- Inside the
build
method store the list of widgets and display them inside the carousel with their respective labels:
If you run the app the carousel will look like this:
To add the floating selector follow these steps:
- Add two boolean lists:
- Modify the
onPageChanged
property of theCarouselOptions
widget.
- Display the row of Widgets inside a
Card
containing the Text, and show an underline to highlight the option that is selected. The highlighter can be created like this:
The floating selector will look like this:
Bottom information section
This is just a simple information section that will look like this:
The UI code for this is available here.
Improve responsiveness
Although the web app is quite responsive, you will still notice some overflows and the UI design is not comfortable to view on smaller screens of mobile devices. To fix this, we will use a responsive layout to build and resize the widgets as per the device screen size.
We will set some breakpoints for smallScreen
, mediumScreen
, largeScreen
to rebuild the widgets with the new layout as that breakpoint is reached. You can use the code below to achieve this:
Now you can define different widget layouts for different screen sizes. For smaller screens, it is preferable to show a drawer
with the top bar options. For this, we will be using a different AppBar
widget. The hamburger icon will be visible by default on the app bar if we define it in the drawer
property of the Scaffold.
The UI for the Drawer will be like this:
UI code for the Drawer is here.
In this way, you can define different layouts for varying screen sizes.
The final version will look like this on desktop and mobile browsers:
Conclusion
Hopefully, this article will help you to get started with Flutter Web. In the next part of the Flutter Web series, we will try to improve this UI by adding some animations and theming.
You can try out the Flutter Web app here.
Official Flutter Web Docs:
The GitHub repo of this project is available in the following link:
If you like this project, then please “Star” (⭐️) the GitHub repo.
Originally published on Codemagic Blog:
Check out my other articles
If you want to support me and want me to continue writing Flutter articles and building some interesting Flutter projects, please contribute to my Patreon page below:
You can follow me on Twitter and find some of my projects on GitHub. Also, don’t forget to checkout my Website. Thank you for reading, if you enjoyed the article make sure to show me some love by hitting that clap (👏) button!
Happy coding…
Souvik Biswas