flutter_html_css_text_metrics 0.3.0 copy "flutter_html_css_text_metrics: ^0.3.0" to clipboard
flutter_html_css_text_metrics: ^0.3.0 copied to clipboard

A flutter_html extension that applies letter-spacing, word-spacing, text-decoration-thickness and the font-family fallback list from an element's inline style.

example/example.md

Example #

flutter_html has no letter-spacing, word-spacing or text-decoration-thickness support of its own. Its Style class already carries a field for each of them, and generateTextStyle() already hands each field to the TextStyle behind every rendered span, but the CSS declaration parser has no case for any of the three properties, so nothing ever sets them. The same parser reads a font-family list and keeps only its first entry. This extension connects the two ends.

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

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

  @override
  Widget build(BuildContext context) => MaterialApp(
        home: Scaffold(
          body: Html(
            data: '''
              <div style="font-size: 12px; font-weight: 500;
                          letter-spacing: 0.1666666667em;
                          text-transform: uppercase;">
                What text-overline asks for, written out as inline CSS.
              </div>

              <p style="word-spacing: 6px;">
                Six extra pixels on every space.
              </p>

              <p style="text-decoration: underline;
                        text-decoration-thickness: 3;">
                An underline three times the thickness the font defines.
              </p>

              <p style="font-size: 40px; text-decoration: underline;
                        text-decoration-thickness: 10px;">
                An underline about ten pixels thick. It is an approximation.
              </p>

              <p style="font-family: Fira Code, Menlo, monospace;">
                The whole family list survives, not only Fira Code.
              </p>
            ''',
            extensions: const [CssTextMetricsHtmlExtension()],
          ),
        ),
      );
}

void main() => runApp(const ExampleApp());

What it supports #

  • letter-spacing and word-spacing, as a length in px, em or rem, or as a unitless zero.
  • letter-spacing: normal and word-spacing: normal, which hand the spacing back to the font.
  • text-decoration-thickness: auto and from-font, which ask for the thickness the font defines.
  • text-decoration-thickness: <number>, which multiplies that thickness.
  • text-decoration-thickness as a length in px, em or rem, or as a percentage of 1em, which approximates the multiplier: the length divided by one twelfth of the element's font-size. 10px on a 40 px font asks for 3.0, and paints a 2.50 px line where the font's own is 1.00 px.
  • font-family: A, B, C, which sets family A and keeps B and C as fallbacks.
  • !important on any of those declarations.

Behaviour #

letter-spacing and word-spacing inherit in CSS. The extension applies them to the element and to its descendants. A descendant that declares its own value overrides the ancestor. A descendant that already carries a value from somewhere else keeps it: a <code> element stays on its monospace family under an inherited font-family.

text-decoration-thickness does not inherit, and applies to the element alone. A length and a percentage are an approximation, because Flutter takes a multiplier of the font's own line and exposes no way to read that line's thickness. Ask for a unitless multiple when the line has to be exact.

normal resolves to Flutter's null, not to zero. Zero would pin the tracking at exactly zero. null lets the font apply its own, and it clears the tracking your theme cascaded in. Material's bodyMedium carries letterSpacing: 0.25, and flutter_html copies that onto every span.

An em length resolves against the element's own computed font-size. A rem length resolves against the root font size, which flutter_html takes from the surrounding DefaultTextStyle. That style carries no font size in some contexts, and the extension then falls back to 14.

A value the extension cannot map is ignored, not guessed at. The element renders exactly as it would have without the extension. The same goes for an element whose final inline style holds none of these properties.

The extension reads the inline style="" attribute only. It does not parse <style> blocks or stylesheets.

Pairing with a utility-class extension #

A utility-class package expands classes into inline CSS, then drops the declarations nothing downstream can render. Each one widens that set for the companion extensions it recognises.

Neither package recognises CssTextMetricsHtmlExtension: flutter_html_bootstrap 0.1.1 and flutter_html_vuetify 0.1.0. flutter_html_vuetify 0.1.1 does not list it either. Vuetify's typography classes therefore still lose their letter-spacing declaration. Registering this extension alongside one of those packages does not bring it back.

Until a release of those packages adds this one, write the property into the inline style attribute yourself:

Html(
  data: '<div style="font-size: 12px; letter-spacing: 0.1666666667em;">'
      'OVERLINE</div>',
  extensions: const [CssTextMetricsHtmlExtension()],
);

Registration order does not matter against a utility-class extension. That extension expands its classes during the preStyling step, and this one reads the result during the preProcessing step, which always runs later.

It matters against flutter_html_css_font_size. That extension acts at the preProcessing step too, and flutter_html runs the extensions that match at a step in registration order. List it first:

Html(
  data: '<div style="font-size: 2em">'
      '<span style="font-size: 1.5em; letter-spacing: 0.1em">M</span></div>',
  extensions: const [
    CssFontSizeHtmlExtension(), // must come first
    CssTextMetricsHtmlExtension(),
  ],
);

The letter spacing is 4.2 in that order and 2.1 in the other, because this extension reads a resolved font-size only once the font size extension has written one. Where the declaring element's parent renders at the root size, as in <div style="font-size: 2em; letter-spacing: 0.1em">, both orders give 2.8.

0
likes
160
points
53
downloads

Documentation

API reference

Publisher

verified publisherchaosworld.cc

Weekly Downloads

A flutter_html extension that applies letter-spacing, word-spacing, text-decoration-thickness and the font-family fallback list from an element's inline style.

Repository (GitLab)
View/report issues
Contributing

Topics

#flutter-html #css #html #extension #letter-spacing

License

MPL-2.0 (license)

Dependencies

flutter, flutter_html, html

More

Packages that depend on flutter_html_css_text_metrics