Sub6Resources / flutter_html

A Flutter widget for rendering static html as Flutter widgets (Will render over 80 different html tags!)
https://pub.dev/packages/flutter_html
MIT License
1.79k stars 860 forks source link

[QUESTION] Apparent whitespace messes up alignment and text decoration. #1141

Closed proxy2501 closed 2 years ago

proxy2501 commented 2 years ago

Hi there, I have run into an issue where Html Widgets seem to add extra white space without being told to do so, which causes them to "fill out" all available horizontal space.

Consequently, they will appear to be left-aligned, even if placed inside a parent that tries to center- or right-align its children.

The code below should reproduce this behavior. I have also styled everything with an 'underline' text decoration, because this makes it easier to see the apparent additional white space that gets added.

import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';

void main() => runApp(const MaterialApp(home: UnderlineDemoPage()));

class UnderlineDemoPage extends StatelessWidget {
  const UnderlineDemoPage({super.key});

  @override
  Widget build(BuildContext context) {
    final Map<String, Style> htmlStyle = {
      "*": Style(
        textDecoration: TextDecoration.underline,
      ),
    };

    return Scaffold(
      appBar: AppBar(
        title: const Text('Html issue demo'),
        centerTitle: true,
      ),
      body: Column(
        children: [
          const Text('Not wrapped:'),
          Html(
            data: '<p>html text</p>',
            style: htmlStyle,
          ),
          const Text('Centered:'),
          Center(
            child: Html(
              data: '<p>html text</p>',
              style: htmlStyle,
            ),
          ),
          const Text('Right aligned:'),
          Align(
            alignment: Alignment.topRight,
            child: Html(
              data: '<p>html text</p>',
              style: htmlStyle,
            ),
          )
        ],
      ),
    );
  }
}

It is worth noting that the underline decoration only affects the white space if the "*" selector is used, which may be intended behavior, but the addition of the white space itself seems problematic.

I have searched though the documentation, but have not been able to find a solution yet - am I doing something wrong?

Thanks for your time!

erickok commented 2 years ago

The Html widget fills horizontal space, unless you tell it to shrinkWrap. Is that what you are looking for?

proxy2501 commented 2 years ago

That does indeed address the alignment issue, thank you! However the "problem," if you can call it that, of additional white space being added below the text still seems to persist.

I imagine this is quite unique to my use case - I receive some API data that may be either HTML or plain text, and I wish to render it with an underlined text decoration. Therefore selecting "p" won't do the trick.

But using the "*" selector also makes a full screen width horizontal line appear below the text. I have modified my example code to illustrate this:

import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';

void main() => runApp(const MaterialApp(home: UnderlineDemoPage()));

class UnderlineDemoPage extends StatelessWidget {
  const UnderlineDemoPage({super.key});

  @override
  Widget build(BuildContext context) {
    final Map<String, Style> htmlStyle = {
      "*": Style(
        textDecoration: TextDecoration.underline,
      ),
    };

    String data =
        '<p>A very very very very very very very very very very very very very long html text</p>';

    return Scaffold(
      appBar: AppBar(
        title: const Text('Html issue demo'),
        centerTitle: true,
      ),
      body: Column(
        children: [
          const Text('Not wrapped:'),
          Html(
            data: data,
            style: htmlStyle,
            shrinkWrap: true,
          ),
          const Text('Centered:'),
          Center(
            child: Html(
              data: data,
              style: htmlStyle,
              shrinkWrap: true,
            ),
          ),
          const Text('Right aligned:'),
          Align(
            alignment: Alignment.topRight,
            child: Html(
              data: data,
              style: htmlStyle,
              shrinkWrap: true,
            ),
          )
        ],
      ),
    );
  }
}

It is simply that case that text decoration should never be applied when selecting everything?

Thanks again for taking the time.

erickok commented 2 years ago

Do you have a screenshot? It's a bit hard to imagine the issue and I'm not at a computer with the code now to test myself.

proxy2501 commented 2 years ago

html Certainly, here is a screenshot of it happening on emulator.

erickok commented 2 years ago

You might need to set the paddings to the (implicit) body and the p tags to EdgeInsets.zero to achieve what you want.

proxy2501 commented 2 years ago

I tried setting both padding and margin for "body" and "p" to EdgeInsets.zero, and while the padding did not seem make a difference, the margin did. It works perfectly with short texts that do not span multiple lines.

I now (almost!) have what I want - the only remaining problem is that the remaining white space to the right of the text's trailing end becomes underlined also:

html2

This may be fine for my case - I could try selecting p tags instead of "*" for the text decoration, and run a check somewhere else for whether the text data is actually HTML or not.

Thank you very much for your help.

erickok commented 2 years ago

Yes, by styling on * you get this behaviour and indeed the solution is to only style the actual text.

Glad it works now.