flutter_html_css_text_metrics

pub version pipeline license GitLab

A flutter_html extension that renders the CSS letter-spacing, word-spacing and text-decoration-thickness properties, and the tail of a font-family list. flutter_html 3.0.0 parses none of the first three and keeps only the first family. It drops the rest, and there is no error and no warning. It writes the values into the element's Style. No released utility-class extension recognises it yet.

Contents

Features

  • letter-spacing and word-spacing set the tracking and the space width. Both inherit, and a descendant with its own value wins.
  • text-decoration-thickness takes auto, from-font and a unitless multiple of the thickness the font defines. A length and a percentage are accepted as an approximation of that multiple. It does not inherit.
  • font-family: A, B, C renders as family A with B and C as fallbacks, quoted and multi-word names included.
  • A length resolves in px, em and rem. rem takes the context's DefaultTextStyle size, or 14 when that is null. !important is accepted.
  • normal is not zero. It hands the spacing back to the font and clears the tracking a Material theme cascaded in: bodyMedium carries letterSpacing: 0.25.
  • A value this extension cannot map leaves the element as it was. There is no error and no warning.
  • doc/coverage.md measures what each framework emits, and why font-family is outside kCssTextMetricsProperties.

Getting started

dependencies:
  flutter_html: ^3.0.0
  flutter_html_css_text_metrics: ^0.3.0

Usage

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

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

Before you register it

This extension reads the inline style at the preProcessing step, never a tag name. Order against a utility-class extension does not matter: those write the inline style one step earlier.

List flutter_html_css_font_size before this one. flutter_html runs the extensions matching at a step in list order, and that package resolves an em, % or rem font-size this one would otherwise read unresolved. A thickness length needs it too: the font size is the divisor.

A TagExtension discards these properties in either order. It builds its own widget and never reads a Style. There is no error and no warning. Set the spacing on the TextStyle its builder returns.

Html(
  data: '<v-chip style="letter-spacing: 2px;">Tag</v-chip>',
  extensions: [
    const CssTextMetricsHtmlExtension(),
    TagExtension(tagsToExtend: const {'v-chip'}, child: const Text('Tag')), // spacing never applies
  ],
);

flutter_html_bootstrap 0.1.1 and flutter_html_vuetify 0.1.0 do not recognise CssTextMetricsHtmlExtension, and Vuetify 0.1.1 does not list it either. Vuetify's typography classes therefore lose their letter-spacing. Bootstrap 5.3 emits none of the three, so it suppresses nothing here. Write the property into an inline style attribute until a release lists it.

Limitations

  • text-decoration-thickness is a multiplier, never a length. Flutter exposes no way to read the thickness a font defines, so a length is an approximation: the length divided by one twelfth of the font size. A percentage is a share of 1em. Ask for a unitless multiple when the line has to be exact.
  • Only px, em, rem and % reach that approximation. pt, cm and vw are left alone, because flutter_html_css_units 0.1.0 has no text-decoration-thickness in its property list. Measured on a red underline at font-size: 40px: 1.00 px of line with nothing declared, 2.50 px for 10px and for 0.25em, 4.75 px for 50%, and 1.00 px for 30pt.
  • A child that declares its own text-decoration erases the ancestor's line over the child's text, and paints its own line in the ancestor's colour. One TextStyle cannot carry both. Measured at font-size: 40px, parent underline red and child overline blue: 320 red pixels against 560 with no child declaration.
  • An em length on an element that also sets font-size in em or % resolves against the root size, because that font size is still unresolved here. flutter_html drops a rem font-size outright, so an em tracking on a Vuetify typography class follows the inherited size.
  • Listing flutter_html_css_font_size first closes that gap, and so does setting the font-size in px. Measured in that package's tests, on a nested em size: 4.2 with it first, 2.1 with this extension first.
  • text-indent, word-break, overflow-wrap and text-underline-offset are out of scope. Style has no field for them.
  • Only the inline style is read. <style> blocks and stylesheets are not.

Full list: doc/limitations.md.

Additional information

Issues and merge requests go to the GitLab repository. The other extension that writes text properties into Style is flutter_html_css_text_overflow.

CI, publishing and Renovate are described in CONTRIBUTING.md.