flutter_html_css_font_size 0.2.0 copy "flutter_html_css_font_size: ^0.2.0" to clipboard
flutter_html_css_font_size: ^0.2.0 copied to clipboard

A flutter_html extension that renders a relative CSS font-size. flutter_html 3.0.0 drops rem and compounds em and percentages.

example/example.md

Example #

flutter_html 3.0.0 gets four relative font sizes wrong. The rem branch of ExpressionMapping.expressionToFontSize is commented out, so font-size: 2rem is dropped at parse time and the element renders at the size it inherits. An em or a percentage parses, and is then applied once per level of the tree below the element that declares it, so font-size: 2em renders its text at 56 where CSS says 28. A tag with a per-tag default inside such an element is resolved against the parent's raw 2em, so an h1 there renders at 4 where CSS says 56. A relative <font size="+2"> renders at 14 rather than at step 5. There is no error and no warning in any of the four. This extension writes the CSS size into the element and its subtree.

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

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

  @override
  Widget build(BuildContext context) => MaterialApp(
        home: Scaffold(
          body: Html(
            data: '''
              <div style="font-size: 2rem;">
                Twice the root size, which is 28 logical pixels.
              </div>

              <div style="font-size: 0.875rem;">
                Seven eighths of it, at 12.25.
              </div>

              <div style="font-size: 1.5rem;">
                A heading size, with
                <span style="font-size: 0.875rem;">a smaller run inside it.</span>
              </div>

              <div style="font-size: 2em;">
                Twice the parent size, at 28, and
                <span style="font-size: 1.5em;">1.5 times that, at 42.</span>
              </div>

              <div style="font-size: larger;">
                One step up from the inherited size.
              </div>

              <div style="font-size: 2em;">
                <h1>A heading here renders at 56, not at 4.</h1>
                <small>And this run at 23.24, not at 1.66.</small>
              </div>
            ''',
            extensions: const [CssFontSizeHtmlExtension()],
          ),
        ),
      );
}

The root size #

rem resolves against the document's root font size. flutter_html takes that from the ambient DefaultTextStyle, and uses FontSize.medium, which is 14, where that states none. A browser uses 16, so the same HTML renders smaller here than it does on the web.

Pass the browser's number to get the browser's sizes:

const CssFontSizeHtmlExtension(rootFontSize: 16);

With a utility-class extension #

Bootstrap's fs-1 to fs-6 and every Vuetify text-* typography class state their size in rem. Register either package with this one and those classes render at their real size. Order does not matter.

Html(
  data: '<p class="fs-3">Bootstrap fs-3, 1.75rem</p>',
  extensions: const [
    BootstrapUtilitiesHtmlExtension(),
    CssFontSizeHtmlExtension(),
  ],
);

Order matters against an extension that reads Style.fontSize at the preProcessing step, such as flutter_html_css_text_metrics. List this one first, or that one resolves its em lengths against the old size.

flutter_html_bootstrap 0.1.1 and flutter_html_vuetify 0.1.0 need no change for this. Both treat font-size as a property flutter_html renders. So both emit the declaration, and neither reports the class as unsupported. Only the rem value goes missing.

Bootstrap 0.1.2 and Vuetify 0.1.1 differ. From those versions on they suppress a font-size whose value is rem, smaller or larger. Bootstrap then reports fs-1 to fs-6 as unsupported classes. Vuetify reports its typography classes as partly rendered. Both reports go to FlutterError.reportError. Neither throws. Registering CssFontSizeHtmlExtension stops the suppression and the report, because each package reads it from its companion registry as a fontSizeUnits entry.

Register this extension either way. Against bootstrap 0.1.1 and vuetify 0.1.0 it renders the size. From bootstrap 0.1.2 and vuetify 0.1.1 it also keeps the declaration.

Reading a font size from another extension #

resolvedFontSizeOf answers what size an element should render at. It works at every step, including the ones that run before flutter_html resolves relative sizes.

import 'package:flutter/foundation.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html_css_font_size/flutter_html_css_font_size.dart';

class MyExtension extends HtmlExtension {
  const MyExtension();

  @override
  Set<String> get supportedTags => const {};

  @override
  bool matches(ExtensionContext context) =>
      context.currentStep == CurrentStep.preStyling;

  @override
  void beforeStyle(ExtensionContext context) {
    final styledElement = context.styledElement;
    if (styledElement == null) return;

    // An `em` length of your own can now be resolved.
    final fontSize = resolvedFontSizeOf(styledElement);
    debugPrint('${styledElement.name} renders at $fontSize');
  }
}

It reads the DOM: the inline style="" of the element and of every ancestor, plus flutter_html's own per-tag defaults, such as 2em for h1. A size set through Html(style: ...) or by another extension is invisible to it.

What is left alone #

px, a unitless 0 and xx-small to xx-large all reach Style.fontSize without this extension, and none of them compounds, so it does not touch them. calc(), inherit and units such as pt and vw are not handled by either.

One case stays wrong with this extension registered. It is measured against flutter_html 3.0.0 and it is in doc/relative-sizes.md.

An em resolves against the inline sizes of the ancestor chain. A size set through Html(style: ...) or in a <style> block is invisible there, so a 2em under a 20px div renders at 28 where CSS says 40. There is no error and no warning.

Every size on this page is a Flutter logical pixel, the unit Style.fontSize holds. It is not a physical device pixel.

0
likes
160
points
51
downloads

Documentation

API reference

Publisher

verified publisherchaosworld.cc

Weekly Downloads

A flutter_html extension that renders a relative CSS font-size. flutter_html 3.0.0 drops rem and compounds em and percentages.

Repository (GitLab)
View/report issues
Contributing

Topics

#flutter-html #css #html #extension #font-size

License

MPL-2.0 (license)

Dependencies

flutter, flutter_html, html

More

Packages that depend on flutter_html_css_font_size