Open In App

Flutter with HTML

Last Updated : 31 Jan, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Flutter is growing with its libraries and community. Earlier, we could use Machine Learning and Flutter together to create powerful applications. Now, we can combine Flutter and HTML too. If there is a static HTML webpage that we want to render in our application that is built using Flutter. With this flutter_html Flutter package, we can render the entire webpage in the Flutter application.  

HTML and Flutter are different, if we want to render an HTML page with CSS in Flutter, it seems weird. This means how is it possible that HTML code will render on-screen using Flutter. Well, it sounds difficult but until flutter_html package in Flutter was not published. In this article, we will learn about the working of this Flutter library by creating a sample app.
 

Implementation:

Step 1: To commence with, create a Flutter Project.

Step 2: Add dependency

In the pubspec.yaml file add the flutter_html package inside the dependencies section.

To install it run pub get in the terminal of IDE or simply press CTRL+S in Windows to add it.

Step 3: Import Dependency.

In the main.dart file, import dependency as –

Dart




import 'package:flutter_html/flutter_html.dart';


Step 4: Get the HTML page.

Now, get the HTML page that we want to display on the screen in Flutter. For Example, we are taking an HTML sample code:

HTML




const htmlData = r"""
<p id='top'><a href='#'>This is the link</a></p>
  
      <h1>Header 1</h1>
      <h2>Header 2</h2>
      <h3>Header 3</h3>
      <h4>Header 4</h4>
      <h5>Header 5</h5>
      <h6>Header 6</h6>
      <h3>This is HTML page that we want to integrate with Flutter.</h3>
      """;


We cannot assign htmlData to the Text widget, we have to use the flutter_html package to render this htmlData on the app.

Step 5: Use HTML() widget and assign values to its properties. We will assign htmlData to its data property, and all the Html tags to the tagsList.

Dart




Html(
          data: htmlData,
          tagsList: Html.tags,
          style: {
            "table": Style(
              backgroundColor: Color.fromARGB(0x50, 0xee, 0xee, 0xee),
            ),
            "tr": Style(
              border: Border(bottom: BorderSide(color: Colors.grey)),
            ),
            "th": Style(
              padding: EdgeInsets.all(6),
              backgroundColor: Colors.grey,
            ),
            "td": Style(
              padding: EdgeInsets.all(6),
              alignment: Alignment.topLeft,
            ),
            'h5': Style(maxLines: 2, textOverflow: TextOverflow.ellipsis),
          },
        ),


Source Code:

Dart




import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
  
void main() => runApp(new MyApp());
  
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.green,
      ),
      home: MyHomePage(),
    );
  }
}
  
class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}
  
const htmlData = r"""
<p id='top'><a href='#'>This is the Link</a></p>
  
      <h1>Header 1</h1>
      <h2>Header 2</h2>
      <h3>Header 3</h3>
      <h4>Header 4</h4>
      <h5>Header 5</h5>
      <h6>Header 6</h6>
      <h3>This is HTML page that we want to integrate with Flutter.</h3>
       
""";
  
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: AppBar(
        title: Text('GeeksForGeeks'),
        centerTitle: true,
      ),
      body: SingleChildScrollView(
        child: Html(
          data: htmlData,
          tagsList: Html.tags,
          style: {
            "table": Style(
              backgroundColor: Color.fromARGB(0x50, 0xee, 0xee, 0xee),
            ),
            "tr": Style(
              border: Border(bottom: BorderSide(color: Colors.grey)),
            ),
            "th": Style(
              padding: EdgeInsets.all(6),
              backgroundColor: Colors.grey,
            ),
            "td": Style(
              padding: EdgeInsets.all(6),
              alignment: Alignment.topLeft,
            ),
            'h5': Style(maxLines: 2, textOverflow: TextOverflow.ellipsis),
          },
        ),
      ),
    );
  }
}


Output:

Step 6: We can create custom tags and then add them to the HTML tags list using tagList property tagList: HTML.tags..add(‘flutter’). Like here we are creating a custom ‘flutter’ tag and adding it to the HTML tags list. For Example: <flutter></flutter>

We need to assign the HTML data to the data property of the HTML() widget. 

Every HTML tag whether it is a table tag or ordered list tag all are supported along with the customized tags functionality. Also in HTML() widget style property, we can give styles to the HTML tags and custom tags. We can also add styling to images being rendered from networks and domains. For a better understanding see the below code.

Source Code:

Dart




void main() {
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
  
void main() => runApp(new MyApp());
  
class MyApp extends StatelessWidget {
    
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Tutorial',
      theme: new ThemeData(
        primarySwatch: Colors.green,
      ),
      home: MyHomePage(),
    );
  }
}
  
class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}
  
const htmlData = r"""
<body style="background-color:powderblue;">
      <h3>Support for math equations:</h3>
      Solve for <var>x<sub>n</sub></var>: log<sub>2</sub>(<var>x</var><sup>2</sup>+<var>n</var>) = 9<sup>3</sup>
     <h3>Inline Styles:</h3>
        
<p>This should be <span style='color: blue;'>BLUE style='color: blue;'</span></p>
  
      <h3>Table support (with custom styling!):</h3>
      <table>
      <colgroup>
        <col width="50%" />
        <col span="2" width="25%" />
      </colgroup>
      <thead>
      <tr><th>One</th><th>Two</th><th>Three</th></tr>
      </thead>
      <tbody>
      <tr>
        <td rowspan='2'>Rowspan</td><td>Data</td><td>Data</td>
      </tr>
      <tr>
        <td colspan="2"><img alt='Google' src='https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png' /></td>
      </tr>
      </tbody>
      <tfoot>
      <tr><td>fData</td><td>fData</td><td>fData</td></tr>
      </tfoot>
      </table>
      <h4>Below is the custom tag: Flutter tag</h4>
      <flutter vertical></flutter>
      <h3>List support:</h3>
      <ol>
            <li>This</li>
            <li>
<p>is</p>
</li>
            <li>
            ordered
            <ul>
            <li>This is a</li>
            <li>nested</li>
            <li>unordered list
            </li>
            </ul>
            </li>
      </ol>
      <h3>Images are also supported:</h3>
      <h3>Network png</h3>
      <h3>Network svg</h3>
     <h3>Data uri (with base64 support)</h3>
      <img alt='Red dot (png)' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==' />
      <img alt='Green dot (base64 svg)' src='data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB2aWV3Qm94PSIwIDAgMzAgMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxjaXJjbGUgY3g9IjE1IiBjeT0iMTAiIHI9IjEwIiBmaWxsPSJncmVlbiIvPgo8L3N2Zz4=' />
      <img alt='Green dot (plain svg)' src='data:image/svg+xml,%3C?xml version="1.0" encoding="UTF-8"?%3E%3Csvg viewBox="0 0 30 20" xmlns="http://www.w3.org/2000/svg"%3E%3Ccircle cx="15" cy="10" r="10" fill="yellow"/%3E%3C/svg%3E' />
         
""";
  
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: AppBar(
        title: Text('GeeksForGeeks'),
        centerTitle: true,
      ),
      body: SingleChildScrollView(
        child: Html(
          data: htmlData,
          tagsList: Html.tags..add("flutter"),
          style: {
              
            // add style to the tags in HTML code
            "table": Style(
              backgroundColor: Color.fromARGB(0x50, 0xee, 0xee, 0xee),
            ),
            "tr": Style(
              border: Border(bottom: BorderSide(color: Colors.grey)),
            ),
            "th": Style(
              padding: EdgeInsets.all(6),
              backgroundColor: Colors.grey,
            ),
            "td": Style(
              padding: EdgeInsets.all(6),
              alignment: Alignment.topLeft,
            ),
            'h5': Style(maxLines: 2, textOverflow: TextOverflow.ellipsis),
          },
          customRender: {
            "table": (context, child) {
              return SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: (context.tree as TableLayoutElement).toWidget(context),
              );
            },
              
            // adding customizable tag
            "flutter": (RenderContext context, Widget child) {
                
              // giving style to Flutter tag with FlutterLogo() widget
              return FlutterLogo(
                style: (context.tree.element!.attributes['horizontal'] != null)
                    ? FlutterLogoStyle.horizontal
                    : FlutterLogoStyle.markOnly,
                textColor: context.style.color!,
                size: context.style.fontSize!.size! * 5,
              );
            },
          },
          customImageRenders: {
              
            // We can give similar features to elements
            // from the same domain like for flutter.dev
            // We can define any number of networkSourceMatcher
            networkSourceMatcher(domains: ["flutter.dev"]):
                (context, attributes, element) {
              return FlutterLogo(size: 36);
            },
            networkSourceMatcher(domains: ["mydomain.com"]): networkImageRender(
              headers: {"Custom-Header": "some-value"},
              altWidget: (alt) => Text(alt ?? ""),
              loadingWidget: () => Text("Loading..."),
            ),
            // If relative paths starts with /wiki, 
            // prefix them with a base url
            (attr, _) =>
                    attr["src"] != null && attr["src"]!.startsWith("/wiki"):
                networkImageRender(
                    mapUrl: (url) => "https://upload.wikimedia.org" + url!),
              
            // If links for images are broken use Custom placeholder
            // image
            networkSourceMatcher():
                networkImageRender(altWidget: (_) => FlutterLogo()),
          },
          onCssParseError: (css, messages) {
              
            //If error occurs while applying CSS to HTML
            print("css that errored: $css");
            print("error messages:");
            messages.forEach((element) {
              print(element);
            });
          },
        ),
      ),
    );
  }
}


Output:



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads