flutter_html_css_flex
A flutter_html extension that lays out CSS
flexbox containers, single-axis grid containers and gap. flutter_html 3.0.0 renders
none of the three. Its parser maps display: flex to display: inline, so a flex
container renders as inline text. This extension replaces the container's build instead
of wrapping it. No released utility-class extension recognises it yet.
Contents
Features
- The extension lays out
display: flex,inline-flex,gridandinline-gridcontainers. - It repairs
Style.display, whichflutter_htmlsets toinlinefor all four values. It repairs it for another nineteen keywords it does not lay out as well, fromtabletocontents, so those stop demoting a block element to inline. - It reads
flex-direction,flex-flow,flex-wrap,justify-content,align-itemsandalign-contenton the container. - It reads
flex,flex-grow,flex-basis,align-selfandorderon each item. - It reads
gap,row-gapandcolumn-gapinpx,emandrem. On the container,remresolves against the container's own font size, not the root. - It reads
grid-template-columnswith<length>,<flex>,autoandrepeat(). - It keeps the element's box: margin, padding, border, background, width, height and
idanchors still work. - The property map is in doc/properties.md.
Getting started
dependencies:
flutter_html: ^3.0.0
flutter_html_css_flex: ^0.3.0
Usage
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html_css_flex/flutter_html_css_flex.dart';
Html(
data: '''
<div style="display: flex; gap: 16px; align-items: center">
<div style="flex: 0 0 120px">Sidebar</div>
<div style="flex-grow: 1">Body</div>
</div>
''',
extensions: const [CssFlexHtmlExtension()],
);
Before you register it
This extension matches on the inline style, never on the tag name. It cannot make
flutter_html render a tag that has no renderer. A TagExtension does that.
A custom tag such as <v-row> needs a TagExtension to become an element with children
at all. List this extension first:
Html(
data: '<v-row style="display: flex; gap: 8px"><p>One</p><p>Two</p></v-row>',
extensions: [
const CssFlexHtmlExtension(), // must come first
TagExtension(tagsToExtend: const {'v-row'}, child: const SizedBox.shrink()),
],
);
flutter_html builds an element with the first extension in the list that matches it.
Listed second, the TagExtension's widget renders and the layout is lost. There is no
error and no warning.
List flutter_html_css_size_constraints 0.1.0 before this extension. That
extension hands the element on to the next match; this one does not. Listed after it,
max-width, min-width, max-height and min-height never apply. There is no error
and no warning.
Html(
data: '<div style="display: flex; max-width: 320px"><p>One</p><p>Two</p></div>',
extensions: const [
CssFlexHtmlExtension(),
CssSizeConstraintsHtmlExtension(), // never runs; max-width never applies
],
);
Order against a utility-class extension does not matter. This extension reads the inline
style at the preProcessing and building steps, both after such an extension expands
its classes.
Released flutter_html_bootstrap 0.1.1 and
flutter_html_vuetify 0.1.0 suppress display: flex, and they are right to.
Unsuppressed, it reaches flutter_html as display: inline and breaks the page. Neither
recognises CssFlexHtmlExtension, and a companion registry entry alone is not enough.
Both suppress display by value, so each needs a code change first. That change is
written in both and not released. Until those two releases, write the
layout into an inline style attribute. Once they ship, d-flex, d-inline-flex,
flex-*, justify-*, align-*, order-* and the gap classes render next to this
extension. d-table and its variants stay suppressed. That is still right: without the
declaration a <div> keeps its own block box. Every other class those extensions handle
keeps working next to this one.
Limitations
- A repaired keyword gets its box level back and nothing more. There is no table
layout, and
table-columnrenders nothing at all, as a column box does in CSS. !importantis not read.display: flex !importantis not recognised, and the container renders as inline text. There is no error and no warning.- An
inline-flexcontainer, and any container underHtml(shrinkWrap: true), has no free main-axis space.flex-growandjustify-contentdo nothing there. There is no error and no warning. - A percentage
flex-basisinside a nested container measures as zero. Use a length there. There is no error and no warning. flex-shrinkparses, and the layout does not act on it. Flutter's flex layout has no shrink phase.flex-growmatches CSS forflex: 1 1 0%. It diverges when two growing items hold different amounts of content.- A wrapping container takes no growth factors and no per-item cross alignment.
Flutter's
Wraphas neither. <a>,<img>,<details>and<ruby>keep their own renderer. Put the container on a wrapping<div>.- Most of CSS Grid is absent. A
grid-template-columnsthis package cannot read falls back to a single column. There is no error and no warning. emandremdo not resolve against the document root. Aremlength takes the container's font size instead.flutter_html_css_font_sizewill close this gap.- A
calc()orvar()value resolves to nothing, and the property keeps its previous value.<style>blocks and stylesheets never reach this extension.
Full list: doc/limitations.md.
Additional information
Issues and merge requests go to the
GitLab repository.
The building step sibling that must come first is
flutter_html_css_size_constraints.
CI, publishing and Renovate are described in CONTRIBUTING.md.