flutter_html_css_size_constraints 0.2.0
flutter_html_css_size_constraints: ^0.2.0 copied to clipboard
A flutter_html extension that renders the CSS max-width, min-width, max-height and min-height properties.
Example #
flutter_html parses plain width and height, but none of the four size
constraint properties. It does not recognise them at all, so max-width: 320px
in your HTML is discarded at parse time without a diagnostic and the element
renders full width. This extension adds them.
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html_css_size_constraints/flutter_html_css_size_constraints.dart';
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) => MaterialApp(
home: Scaffold(
body: Html(
data: '''
<div style="max-width: 320px; background-color: #0d6efd;
color: #ffffff; padding: 12px;">
Never wider than 320px, however wide the window gets.
</div>
<div style="min-height: 96px; background-color: #198754;
color: #ffffff; padding: 12px;">
At least 96px tall, whatever is inside it.
</div>
<div style="width: 900px; max-width: 100%;
background-color: #6c757d; padding: 12px;">
Wants to be 900px, but the max-width constrains it.
</div>
''',
extensions: const [CssSizeConstraintsHtmlExtension()],
),
),
);
}
void main() => runApp(const ExampleApp());
What it supports #
max-width,min-width,max-heightandmin-height, applied as aConstrainedBoxaround the element.pxand the other CSS absolute lengths (pt,pc,in,cm,mm,q), plus a unitless0.%, resolved against the incoming constraints.vw,vh,vminandvmax, resolved againstMediaQuery.sizeOf.em, resolved against the element's own computedfont-size, andrem, resolved against therootFontSizeconstructor argument.rootFontSizedefaults to 14, which isflutter_html's own default, not the browser's 16.noneon amax-*property, which means no constraint.
Behaviour #
- A
min-*beats a conflictingmax-*, which is the CSS rule.min-width: 200px; max-width: 100pxgives a 200px width. It does not raise an assertion. - The
ConstrainedBoxsits outsideflutter_html's own box. Amax-widththerefore constrains awidththat the parser did read. - The extension drops a value it cannot read,
calc()included. That one property gets no constraint. The other three still apply, and nothing throws. - An element whose final inline style has none of the four properties gets no wrapper widget at all.
- The extension reads the inline
style=""attribute only. It does not parse<style>blocks or stylesheets.
Percentages #
A percentage in CSS resolves against the containing block. A ConstrainedBox
does not know its containing block, so this package resolves a percentage
against the incoming constraints instead, read with a LayoutBuilder. For a
block-level element that value is the width the parent handed down, which is
normally the parent's content width.
Heights in Flutter are normally unbounded. A percentage max-height or
min-height therefore usually resolves to nothing, and the extension drops it.
CSS drops it too against a containing block of indefinite height.
A LayoutBuilder cannot do dry layout. Turn percentages off if your Html
widget sits under an IntrinsicHeight or an IntrinsicWidth:
const CssSizeConstraintsHtmlExtension(resolvePercentages: false)
Every unit except % still renders.
Pairing with a utility-class extension #
This extension reads the inline style at the building step. It therefore picks
up the four properties wherever a utility-class extension merged them in, and
registration order does not matter.
Those extensions suppress CSS that nothing can render. They widen that set when
they recognise a companion extension that renders it. They do not recognise this
extension yet. Until a release of theirs adds it, write the four properties in an
inline style attribute rather than using the matching utility classes:
Html(
data: '<div class="p-3" style="max-width: 100%; min-height: 100vh;">Card</div>',
extensions: const [
BootstrapUtilitiesHtmlExtension(), // renders p-3
CssSizeConstraintsHtmlExtension(), // renders the inline style
],
);
Non-standard tags #
This extension matches on the inline style, never on the tag name, so it needs
no tag registration of its own. It also cannot make flutter_html render a tag
that has no renderer. Register a TagExtension for that tag, and this extension
constrains what the TagExtension produces.
Html(
data: '<my-widget style="max-width: 320px;"></my-widget>',
extensions: [
const CssSizeConstraintsHtmlExtension(),
TagExtension(tagsToExtend: const {'my-widget'}, child: const MyWidget()),
],
);