flutter_html_css_percent_size
A flutter_html extension that renders
a percentage width, height, padding and margin. flutter_html 3.0.0 parses
all four but reads no percentage value, so width: 50% is a width of zero,
padding: 5% is no padding, and an <img style="width: 50%"> disappears.
There is no error and no warning. Resolving a percentage needs a
LayoutBuilder, which cannot do dry layout.
Features
| Declaration | Bare flutter_html 3.0.0 |
With this extension |
|---|---|---|
<div style="width: 50%"> |
0 pixels wide | 392 |
<img style="width: 50%"> |
Size(0, 0) |
Size(392, 196), aspect ratio kept |
<div style="padding: 5%"> |
no padding | 39.2 on each side |
<div style="padding: 5% 10px 20px"> |
10, 20, 10, 20 | 39.2, 10, 20, 10 |
<div style="margin-left: 5%"> |
no margin | 39.2 |
Measured in a containing block 784 wide: 50% is 392, 5% is 39.2.
- Writes logical pixels into
Style.width,Style.height,Style.paddingandStyle.marginat thebuildingstep, so the element renders through its normal renderer and a background colour still covers the padding. - Resolves a percentage padding or margin against the containing block's
width on all four sides, as CSS does. Reads the shorthands, the longhands
and the logical
-inlineand-blockforms.
Getting started
dependencies:
flutter_html: ^3.0.0
flutter_html_css_percent_size: ^0.3.0
Usage
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html_css_percent_size/flutter_html_css_percent_size.dart';
Html(
data: '<img src="asset:photo.png" style="width: 50%; padding: 5%">',
extensions: const [CssPercentSizeHtmlExtension()],
);
An Html widget under an IntrinsicHeight or an IntrinsicWidth throws,
because a LayoutBuilder cannot do dry layout. Register
CssPercentSizeHtmlExtension(resolvePercentages: false) there: a percentage
width is then auto, and a percentage padding or margin is zero.
Before you register it
List this extension before any other building step extension that renders the
same element. HtmlParser.buildFromExtension returns on the first match.
Html(
data: '<img src="asset:photo.png" style="width: 50%; object-fit: cover">',
extensions: const [
CssSizeConstraintsHtmlExtension(), // first, so max-width still clamps
CssPercentSizeHtmlExtension(), // before object-fit
CssObjectFitHtmlExtension(), // builds the image, delegates to nobody
],
);
CssObjectFitHtmlExtension builds the image itself and never delegates. List it
first and this extension never runs.
CssSizeConstraintsHtmlExtension delegates, so both run in either order, and
neither order matches CSS. Measured on width: 50%; max-width: 100px: 50 with
it first, 392 with it second, and CSS says 100. Listed second, the max-width
is lost with no error and no warning, so list it first. That order gives
padding: 5%; max-width: 100px a padding of 5, where CSS says 39.2.
A TagExtension never reads a Style, so a percentage never reaches it in
either order, with no error and no warning.
Limitations
- A percentage
heightalmost never resolves. The basis is an unbounded maximum height in an ordinary document. Measured inside aSizedBox(height: 600): still dropped, where CSS computes 300. - A percentage margin does not collapse, because
flutter_htmlcollapses margins before this extension writes the pixels. Measured on two adjacent<div style="margin: 5%">: the paragraphs sit 100 apart, against 61 for the same margin in pixels. calc()and the other CSS functions stay withflutter_html, which renders the percentage as zero. There is no error and no warning.- Only the inline
style=""attribute is read.
The numbers are in doc/measurements.md and the order matrix in doc/composition.md.
Additional information
Issues and merge requests go to the
GitLab repository.
Clamping the same element is
flutter_html_css_size_constraints.
Fitting an image inside its box is
flutter_html_css_object_fit.
A font-size in rem is
flutter_html_css_font_size.
CI, publishing and Renovate are described in CONTRIBUTING.md.