flutter_html_bootstrap_css_utilities_extension

A flutter_html extension that inlines Bootstrap 5.3 utility classes as CSS, so HTML authored against Bootstrap markup renders sensibly in flutter_html.

Features

Renders, as inline CSS flutter_html understands:

  • Spacing (m-*, p-*)
  • Background and text colors, including theme, subtle, and gray tokens, and text-bg-*
  • Text alignment, transform, and decoration
  • Typography (fs-*, fw-*, fst-*, lh-*, font-monospace)
  • Sizing (w-*, h-*)
  • d-none, d-block, d-inline*
  • The border and border-<side> shorthands
  • Vertical-align, and the link utilities

Recognized, but deliberately dropped because flutter_html cannot render them (see Not every Bootstrap utility can render): flexbox and grid, gap-*, positioning and z-*, overflow and wrapping, shadows, opacity, float, object-fit, visibility, user-select-*, pe-none, the border longhands, and rounded-* (which a companion extension restores).

Responsive breakpoint variants (mt-md-3, d-lg-none, ...) are applied unconditionally by default, since inline CSS can't express media queries; set applyResponsiveVariantsUnconditionally: false to ignore them instead.

Getting started

dependencies:
  flutter_html: ^3.0.0
  flutter_html_bootstrap_css_utilities_extension: ^0.1.0

Usage

Html(
  data: '''
    <div class="text-bg-primary" style="margin: 20px;">Primary Text BG</div>
    <div class="text-bg-success" style="padding: 5px;">Success Text BG</div>
    <div class="text-bg-danger">Danger Text BG</div>
  ''',
  extensions: [const BootstrapUtilitiesHtmlExtension()],
);

Not every Bootstrap utility can render

flutter_html 3.0.0 understands 51 CSS properties. This package can compute 78, so roughly 40% of the Bootstrap 5.3 utility surface resolves to CSS that flutter_html would discard. Those declarations are suppressed rather than emitted.

Suppression is a bug fix, not tidiness. display is a property flutter_html parses, but its value parser accepts only block/inline/inline-block/list-item/none and falls through to Display.inline for anything else. So emitting display: flex for d-flex does not do nothing, it turns a block <div> inline and breaks the layout.

What is affected

Category Examples Why
Borders (longhands) border-1border-5, border-primary, rounded-* only the border / border-<side> shorthands are parsed; border-radius needs a companion (below)
Flex, grid and gap d-flex, d-grid, flex-*, justify-content-*, align-*, order-*, gap-* flutter_html lays out inline/block flow only
Positioning position-*, top-*/bottom-*/start-*/end-*, translate-middle*, fixed-top, sticky-*, z-* no positioned-layout concept
Sizing constraints mw-100, mh-100, min-vw-100, min-vh-100 only plain width/height are parsed
Shadows shadow, shadow-sm, shadow-lg, shadow-none box-shadow is not parsed
Opacity opacity-*, link-opacity-* opacity is not parsed
Overflow and wrapping overflow-*, overflow-x-*, overflow-y-*, text-wrap, text-nowrap, text-break not parsed
Interaction pe-none, user-select-* pointer-events / user-select are not parsed
Float and object-fit float-*, object-fit-* not parsed
Visibility visible, invisible visibility is not parsed

Everything else renders normally: spacing, colours, text-bg-*, text alignment and transform, typography, width/height, d-none/d-block/d-inline*, the border shorthand, vertical-align.

Introspecting it

BootstrapUtilitiesHtmlExtension.isSupportedClass('mt-3');   // true
BootstrapUtilitiesHtmlExtension.isSupportedClass('d-flex'); // false

// The full list, generated from the Bootstrap 5.3 grammar (647 classes today):
final broken = myClassList.where(
  BootstrapUtilitiesHtmlExtension.unsupportedClasses.contains,
);

A handful of entries are unsupported only on their own: bg-opacity-50 and friends modulate a colour set by a preceding class, so bg-primary bg-opacity-50 renders even though bg-opacity-50 is listed. -hover variants are listed because inline CSS cannot express :hover at all.

Runtime reporting

By default the extension reports the offending classes once per parsed document through FlutterError.reportError, so they show up in the debug console and in crash reporters that hook FlutterError.onError (Sentry, for example). It never throws and never interrupts rendering. The payload is an UnsupportedBootstrapClassesException listing the classes, the suppressed declarations, and the remediation. Turn it off with:

const BootstrapUtilitiesHtmlExtension(reportUnsupportedClasses: false)

Companion extensions widen the set

Registering a companion extension on the same Html widget makes this package stop suppressing the properties that companion can render:

Companion Adds
flutter_html_css_border_radius_extension border-radius*, i.e. the whole rounded-* family
Html(
  data: '<div class="rounded-3 text-bg-primary">Card</div>',
  extensions: const [
    BootstrapUtilitiesHtmlExtension(),
    CssBorderRadiusHtmlExtension(),
  ],
);

Without it, rounded-* is suppressed and named in the report.

Additional information

This is a light-mode approximation of Bootstrap 5.3's default theme; it does not support :hover/:focus states or media queries, since those have no inline-CSS equivalent. File issues and contributions on the package's GitLab repository.