flutter_html_css_stylesheet

pub version pipeline license GitLab

A flutter_html extension that resolves a CSS stylesheet and writes each element's winning declarations into its inline style="". flutter_html 3.0.0 reads a <style> block itself, then drops every property outside the 51 it parses, so no sibling extension sees them. Register this extension first, or a declaration lands after the extension that needed it, with no error and no warning.

Features

  • Reads every <style> element, in head and body alike, and a stylesheet string you pass in.
  • Resolves the cascade by specificity, then by source order. An inline declaration beats a plain stylesheet declaration; an !important stylesheet declaration beats a plain inline one.
  • flutter_html's own <style> handling has no specificity and no !important. It merges matching rules in read order, then the inline style over them.
  • Empties each <style> element once it has read it, so one cascade resolves those rules. Set consumeStyleElements: false to leave flutter_html's own handling in place.
  • Emptying the block is also what stops flutter_html 3.0.0 throwing on a @media or a @keyframes block, measured with no extension registered. See doc/selectors.md.
  • Passes each declaration through, the 51 included. flutter_html renders those, and a sibling extension renders the rest.
  • Matches with StyledElement.matchesSelector: type, class, id, attribute and :not() selectors, and all four combinators.
  • Names each rule that renders nothing through onUnsupportedRule, once per document.

Getting started

dependencies:
  flutter_html: ^3.0.0
  flutter_html_css_stylesheet: ^0.2.0
  flutter_html_css_border_radius: ^0.2.0

Usage

import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html_css_border_radius/flutter_html_css_border_radius.dart';
import 'package:flutter_html_css_stylesheet/flutter_html_css_stylesheet.dart';

Html(
  data: '''
    <style>
      .card { border-radius: 12px; padding: 12px; }
      #lead { color: #0d6efd; }
    </style>
    <div class="card"><p id="lead">Rounded, and blue.</p></div>
  ''',
  extensions: const [
    CssStylesheetHtmlExtension(), // must come first
    CssBorderRadiusHtmlExtension(),
  ],
);

A <link rel="stylesheet"> is never fetched. Pass the file's text to stylesheet.

Before you register it

List this extension first. Every extension that reads the inline style acts at the preStyling step, and flutter_html runs them in registration order. An extension listed before this one reads the style attribute before the stylesheet reaches it:

Html(
  data: '<style>.card { border-radius: 12px }</style>'
      '<div class="card">Card</div>',
  extensions: const [
    CssBorderRadiusHtmlExtension(), // finds no border-radius, and returns
    CssStylesheetHtmlExtension(),   // writes it a moment too late
  ],
);

The declaration then stays in the style attribute, flutter_html drops it, and nothing rounds. There is no error and no warning.

This extension matches at the preStyling step only, never on a tag name. It cannot make flutter_html render a tag no extension claims. Use a TagExtension.

Released flutter_html_bootstrap 0.1.1 and flutter_html_vuetify 0.1.0 list a companion by the properties it renders. This extension renders none, so neither lists it. Both write into style="" too, and the last declaration of a property wins, so order decides.

Limitations

  • An at-rule renders nothing. @media, @import, @font-face, @keyframes and @supports are left out with every rule inside them, in silence. Set onUnsupportedRule to see them.
  • A pseudo-class outside :root, :empty, :blank, :first-child, :last-child, :only-child, :link, :lang() and :nth-child() matches nothing. So does every pseudo-element, and :visited. There is no error and no warning.
  • :nth-child() takes a plain number, and counts nodes rather than elements, so a text node shifts the count.
  • A custom property such as --brand is dropped, and nothing resolves var().
  • The extension resolves the cascade, not the inheritance. flutter_html inherits the properties it parses; a property only a sibling extension renders does not reach a child element.

Additional information

Issues and merge requests go to the GitLab repository. Rounding an element a stylesheet selects is flutter_html_css_border_radius's job. The border longhands are flutter_html_css_border's.

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