LibWeb: Implement time-traveling inheritance for CSS font-size
Some checks are pending
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run

When setting `font-family: monospace;` in CSS, we have to interpret
the keyword font sizes (small, medium, large, etc) as slightly smaller
for historical reasons. Normally the medium font size is 16px, but
for monospace it's 13px.

The way this needs to behave is extremely strange:
When encountering `font-family: monospace`, we have to go back and
replay the CSS cascade as if the medium font size had been 13px all
along. Otherwise relative values like 2em/200%/etc could have gotten
lost in the inheritance chain.

We implement this in a fairly naive way by explicitly checking for
`font-family: monospace` (note: it has to be *exactly* like that,
it can't be `font-family: monospace, Courier` or similar.)
When encountered, we simply walk the element ancestors and re-run the
cascade for the font-size property. This is clumsy and inefficient,
but it does work for the common cases.

Other browsers do more elaborate things that we should eventually care
about as well, such as user-configurable font settings, per-language
behavior, etc. For now, this is just something that allows us to handle
more WPT tests where things fall apart due to unexpected font sizes.

To learn more about the wonders of font-size, see this blog post:
https://manishearth.github.io/blog/2017/08/10/font-size-an-unexpectedly-complex-css-property/
This commit is contained in:
Andreas Kling 2025-02-25 11:47:03 +01:00 committed by Andreas Kling
parent 263e58bbe9
commit b4e47f198a
Notes: github-actions[bot] 2025-02-25 22:56:32 +00:00
14 changed files with 241 additions and 106 deletions

View file

@ -2437,15 +2437,106 @@ GC::Ptr<ComputedProperties> StyleComputer::compute_style_impl(DOM::Element& elem
return computed_properties;
}
static bool is_monospace(CSSStyleValue const& value)
{
if (value.to_keyword() == Keyword::Monospace)
return true;
if (value.is_value_list()) {
auto const& values = value.as_value_list().values();
if (values.size() == 1 && values[0]->to_keyword() == Keyword::Monospace)
return true;
}
return false;
}
// HACK: This function implements time-travelling inheritance for the font-size property
// in situations where the cascade ended up with `font-family: monospace`.
// In such cases, other browsers will magically change the meaning of keyword font sizes
// *even in earlier stages of the cascade!!* to be relative to the default monospace font size (13px)
// instead of the default font size (16px).
// See this blog post for a lot more details about this weirdness:
// https://manishearth.github.io/blog/2017/08/10/font-size-an-unexpectedly-complex-css-property/
RefPtr<CSSStyleValue> StyleComputer::recascade_font_size_if_needed(
DOM::Element& element,
Optional<CSS::Selector::PseudoElement::Type> pseudo_element,
CascadedProperties& cascaded_properties) const
{
// Check for `font-family: monospace`. Note that `font-family: monospace, AnythingElse` does not trigger this path.
// Some CSS frameworks use `font-family: monospace, monospace` to work around this behavior.
auto font_family_value = cascaded_properties.property(CSS::PropertyID::FontFamily);
if (!font_family_value || !is_monospace(*font_family_value))
return nullptr;
// FIXME: This should be configurable.
constexpr CSSPixels default_monospace_font_size_in_px = 13;
static auto monospace_font_family_name = Platform::FontPlugin::the().generic_font_name(Platform::GenericFont::Monospace);
static auto monospace_font = Gfx::FontDatabase::the().get(monospace_font_family_name, default_monospace_font_size_in_px * 0.75f, 400, Gfx::FontWidth::Normal, 0);
// Reconstruct the line of ancestor elements we need to inherit style from, and then do the cascade again
// but only for the font-size property.
Vector<DOM::Element&> ancestors;
if (pseudo_element.has_value())
ancestors.append(element);
for (auto* ancestor = element.parent_element(); ancestor; ancestor = ancestor->parent_element())
ancestors.append(*ancestor);
NonnullRefPtr<CSSStyleValue> new_font_size = CSS::LengthStyleValue::create(CSS::Length::make_px(default_monospace_font_size_in_px));
CSSPixels current_size_in_px = default_monospace_font_size_in_px;
for (auto& ancestor : ancestors.in_reverse()) {
auto& ancestor_cascaded_properties = *ancestor.cascaded_properties({});
auto font_size_value = ancestor_cascaded_properties.property(CSS::PropertyID::FontSize);
if (!font_size_value)
continue;
if (font_size_value->is_initial() || font_size_value->is_unset()) {
current_size_in_px = default_monospace_font_size_in_px;
continue;
}
if (font_size_value->is_inherit()) {
// Do nothing.
continue;
}
if (font_size_value->is_keyword()) {
current_size_in_px = default_monospace_font_size_in_px * absolute_size_mapping(font_size_value->to_keyword());
continue;
}
if (font_size_value->is_percentage()) {
current_size_in_px = CSSPixels::nearest_value_for(font_size_value->as_percentage().percentage().as_fraction() * current_size_in_px);
continue;
}
if (font_size_value->is_calculated()) {
dbgln("FIXME: Support calc() when time-traveling for monospace font-size");
continue;
}
VERIFY(font_size_value->is_length());
current_size_in_px = font_size_value->as_length().length().to_px(viewport_rect(), Length::FontMetrics { current_size_in_px, monospace_font->with_size(current_size_in_px * 0.75f)->pixel_metrics() }, m_root_element_font_metrics);
};
return CSS::LengthStyleValue::create(CSS::Length::make_px(current_size_in_px));
}
GC::Ref<ComputedProperties> StyleComputer::compute_properties(DOM::Element& element, Optional<Selector::PseudoElement::Type> pseudo_element, CascadedProperties& cascaded_properties) const
{
auto computed_style = document().heap().allocate<CSS::ComputedProperties>();
auto new_font_size = recascade_font_size_if_needed(element, pseudo_element, cascaded_properties);
if (new_font_size)
computed_style->set_property(PropertyID::FontSize, *new_font_size, ComputedProperties::Inherited::No, Important::No);
for (auto i = to_underlying(first_longhand_property_id); i <= to_underlying(last_longhand_property_id); ++i) {
auto property_id = static_cast<CSS::PropertyID>(i);
auto value = cascaded_properties.property(property_id);
auto inherited = ComputedProperties::Inherited::No;
// NOTE: We've already handled font-size above.
if (property_id == PropertyID::FontSize && !value && new_font_size)
continue;
if ((!value && is_inherited_property(property_id))
|| (value && value->is_inherit())) {
if (auto inheritance_parent = element_to_inherit_style_from(&element, pseudo_element)) {

View file

@ -183,6 +183,8 @@ public:
static CSSPixelFraction absolute_size_mapping(Keyword);
RefPtr<Gfx::FontCascadeList const> compute_font_for_style_values(DOM::Element const* element, Optional<CSS::Selector::PseudoElement::Type> pseudo_element, CSSStyleValue const& font_family, CSSStyleValue const& font_size, CSSStyleValue const& font_style, CSSStyleValue const& font_weight, CSSStyleValue const& font_stretch, int math_depth = 0) const;
[[nodiscard]] RefPtr<CSSStyleValue> recascade_font_size_if_needed(DOM::Element&, Optional<CSS::Selector::PseudoElement::Type> pseudo_element, CascadedProperties&) const;
void set_viewport_rect(Badge<DOM::Document>, CSSPixelRect const& viewport_rect) { m_viewport_rect = viewport_rect; }
enum class AnimationRefresh {

View file

@ -1,16 +1,16 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
BlockContainer <body> at (8,16) content-size 784x19 children: not-inline
BlockContainer <pre> at (9,17) content-size 782x17 children: inline
BlockContainer <body> at (8,13) content-size 784x16 children: not-inline
BlockContainer <pre> at (9,14) content-size 782x14 children: inline
InlineNode <span>
frag 0 from TextNode start: 0, length: 1, rect: [9,17 8x17] baseline: 13.296875
frag 0 from TextNode start: 0, length: 1, rect: [9,14 6.5x14] baseline: 10.890625
" "
TextNode <#text>
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,16 784x19]
PaintableWithLines (BlockContainer<PRE>) [8,16 784x19]
PaintableWithLines (BlockContainer<BODY>) [8,13 784x16]
PaintableWithLines (BlockContainer<PRE>) [8,13 784x16]
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)

View file

@ -1,6 +1,6 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x152 children: not-inline
BlockContainer <body> at (8,8) content-size 784x140 children: not-inline
BlockContainer <(anonymous)> at (8,8) content-size 784x17 children: inline
InlineNode <span>
frag 0 from TextNode start: 0, length: 5, rect: [8,8 36.40625x17] baseline: 13.296875
@ -15,27 +15,27 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
"friends"
TextNode <#text>
TextNode <#text>
BlockContainer <div> at (8,25) content-size 784x135 children: not-inline
BlockContainer <div> at (8,25) content-size 784x123 children: not-inline
BlockContainer <(anonymous)> at (8,25) content-size 784x68 children: inline
BreakNode <br>
BreakNode <br>
BreakNode <br>
BreakNode <br>
BlockContainer <pre#out> at (8,109) content-size 784x51 children: inline
frag 0 from TextNode start: 0, length: 10, rect: [8,109 72.203125x17] baseline: 13.296875
BlockContainer <pre#out> at (8,106) content-size 784x42 children: inline
frag 0 from TextNode start: 0, length: 10, rect: [8,106 58.640625x14] baseline: 10.890625
"well: 8, 8"
frag 1 from TextNode start: 11, length: 13, rect: [8,126 95.359375x17] baseline: 13.296875
frag 1 from TextNode start: 11, length: 13, rect: [8,120 77.46875x14] baseline: 10.890625
"hello: 44, 33"
frag 2 from TextNode start: 25, length: 15, rect: [8,143 112.953125x17] baseline: 13.296875
frag 2 from TextNode start: 25, length: 15, rect: [8,134 91.78125x14] baseline: 10.890625
"friends: 44, 25"
TextNode <#text>
BlockContainer <(anonymous)> at (8,176) content-size 784x0 children: inline
BlockContainer <(anonymous)> at (8,161) content-size 784x0 children: inline
TextNode <#text>
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x152]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x140]
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x17]
PaintableWithLines (InlineNode<SPAN>)
TextPaintable (TextNode<#text>)
@ -43,8 +43,8 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600]
TextPaintable (TextNode<#text>)
PaintableWithLines (InlineNode<I>)
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>) [8,25 784x135]
PaintableWithLines (BlockContainer<DIV>) [8,25 784x123]
PaintableWithLines (BlockContainer(anonymous)) [8,25 784x68]
PaintableWithLines (BlockContainer<PRE>#out) [8,109 784x51]
PaintableWithLines (BlockContainer<PRE>#out) [8,106 784x42]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,176 784x0]
PaintableWithLines (BlockContainer(anonymous)) [8,161 784x0]

View file

@ -0,0 +1,35 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x235 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x219 children: not-inline
BlockContainer <(anonymous)> at (8,8) content-size 784x35 children: inline
frag 0 from TextNode start: 0, length: 3, rect: [8,8 55.40625x35] baseline: 27.09375
"abc"
TextNode <#text>
BlockContainer <main> at (8,43) content-size 784x184 children: not-inline
BlockContainer <(anonymous)> at (8,43) content-size 784x70 children: inline
frag 0 from TextNode start: 0, length: 3, rect: [8,43 92.0625x70] baseline: 54.1875
"def"
TextNode <#text>
BlockContainer <article> at (8,113) content-size 784x114 children: not-inline
BlockContainer <(anonymous)> at (8,113) content-size 784x57 children: inline
frag 0 from TextNode start: 0, length: 3, rect: [8,113 69.625x57] baseline: 44.09375
"ghi"
TextNode <#text>
BlockContainer <div> at (8,170) content-size 784x57 children: inline
frag 0 from TextNode start: 0, length: 3, rect: [8,170 59.828125x57] baseline: 44.09375
"jkl"
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x235]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x219]
PaintableWithLines (BlockContainer(anonymous)) [8,8 784x35]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<MAIN>) [8,43 784x184]
PaintableWithLines (BlockContainer(anonymous)) [8,43 784x70]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<ARTICLE>) [8,113 784x114]
PaintableWithLines (BlockContainer(anonymous)) [8,113 784x57]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>) [8,170 784x57]
TextPaintable (TextNode<#text>)

View file

@ -2,7 +2,7 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x17 children: inline
InlineNode <pre>
frag 0 from TextNode start: 0, length: 3, rect: [9,8 19.875x17] baseline: 13.296875
frag 0 from TextNode start: 0, length: 3, rect: [9,10 16.15625x14] baseline: 10.890625
" | "
TextNode <#text>
TextNode <#text>

View file

@ -1,52 +1,52 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x84 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x68 children: not-inline
BlockContainer <div> at (8,8) content-size 784x17 children: inline
frag 0 from BlockContainer start: 0, length: 0, rect: [8,21 60x0] baseline: 0
frag 1 from TextNode start: 0, length: 2, rect: [68,8 82.265625x17] baseline: 13.296875
BlockContainer <html> at (0,0) content-size 800x72 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x56 children: not-inline
BlockContainer <div> at (8,8) content-size 784x14 children: inline
frag 0 from BlockContainer start: 0, length: 0, rect: [8,18 48x0] baseline: 0
frag 1 from TextNode start: 0, length: 2, rect: [56,8 15.59375x14] baseline: 10.890625
" A"
BlockContainer <span#s1> at (8,21) content-size 60x0 inline-block [BFC] children: not-inline
BlockContainer <span#s1> at (8,18) content-size 48x0 inline-block [BFC] children: not-inline
TextNode <#text>
BlockContainer <(anonymous)> at (8,25) content-size 784x0 children: inline
BlockContainer <(anonymous)> at (8,22) content-size 784x0 children: inline
TextNode <#text>
BlockContainer <div> at (8,25) content-size 784x17 children: inline
frag 0 from BlockContainer start: 0, length: 0, rect: [8,38 70x0] baseline: 0
frag 1 from TextNode start: 0, length: 2, rect: [78,25 72.265625x17] baseline: 13.296875
BlockContainer <div> at (8,22) content-size 784x14 children: inline
frag 0 from BlockContainer start: 0, length: 0, rect: [8,32 56x0] baseline: 0
frag 1 from TextNode start: 0, length: 2, rect: [64,22 59.59375x14] baseline: 10.890625
" A"
BlockContainer <span#s2> at (8,38) content-size 70x0 inline-block [BFC] children: not-inline
BlockContainer <span#s2> at (8,32) content-size 56x0 inline-block [BFC] children: not-inline
TextNode <#text>
BlockContainer <(anonymous)> at (8,42) content-size 784x0 children: inline
BlockContainer <(anonymous)> at (8,36) content-size 784x0 children: inline
TextNode <#text>
BlockContainer <div> at (8,42) content-size 784x17 children: inline
frag 0 from BlockContainer start: 0, length: 0, rect: [8,55 73x0] baseline: 0
frag 1 from TextNode start: 0, length: 2, rect: [81,42 69.265625x17] baseline: 13.296875
BlockContainer <div> at (8,36) content-size 784x14 children: inline
frag 0 from BlockContainer start: 0, length: 0, rect: [8,46 58.40625x0] baseline: 0
frag 1 from TextNode start: 0, length: 2, rect: [66.40625,36 57.1875x14] baseline: 10.890625
" A"
BlockContainer <span#s3> at (8,55) content-size 73x0 inline-block [BFC] children: not-inline
BlockContainer <span#s3> at (8,46) content-size 58.40625x0 inline-block [BFC] children: not-inline
TextNode <#text>
BlockContainer <(anonymous)> at (8,59) content-size 784x0 children: inline
BlockContainer <(anonymous)> at (8,50) content-size 784x0 children: inline
TextNode <#text>
BlockContainer <div> at (8,59) content-size 784x17 children: inline
frag 0 from TextNode start: 0, length: 9, rect: [8,59 78.265625x17] baseline: 13.296875
BlockContainer <div> at (8,50) content-size 784x14 children: inline
frag 0 from TextNode start: 0, length: 9, rect: [8,50 63.59375x14] baseline: 10.890625
" A"
TextNode <#text>
BlockContainer <(anonymous)> at (8,76) content-size 784x0 children: inline
BlockContainer <(anonymous)> at (8,64) content-size 784x0 children: inline
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x84]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x68]
PaintableWithLines (BlockContainer<DIV>) [8,8 784x17]
PaintableWithLines (BlockContainer<SPAN>#s1) [8,21 60x0]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x72]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x56]
PaintableWithLines (BlockContainer<DIV>) [8,8 784x14]
PaintableWithLines (BlockContainer<SPAN>#s1) [8,18 48x0]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,25 784x0]
PaintableWithLines (BlockContainer<DIV>) [8,25 784x17]
PaintableWithLines (BlockContainer<SPAN>#s2) [8,38 70x0]
PaintableWithLines (BlockContainer(anonymous)) [8,22 784x0]
PaintableWithLines (BlockContainer<DIV>) [8,22 784x14]
PaintableWithLines (BlockContainer<SPAN>#s2) [8,32 56x0]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,42 784x0]
PaintableWithLines (BlockContainer<DIV>) [8,42 784x17]
PaintableWithLines (BlockContainer<SPAN>#s3) [8,55 73x0]
PaintableWithLines (BlockContainer(anonymous)) [8,36 784x0]
PaintableWithLines (BlockContainer<DIV>) [8,36 784x14]
PaintableWithLines (BlockContainer<SPAN>#s3) [8,46 58.40625x0]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,59 784x0]
PaintableWithLines (BlockContainer<DIV>) [8,59 784x17]
PaintableWithLines (BlockContainer(anonymous)) [8,50 784x0]
PaintableWithLines (BlockContainer<DIV>) [8,50 784x14]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,76 784x0]
PaintableWithLines (BlockContainer(anonymous)) [8,64 784x0]

View file

@ -1,16 +1,16 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x33 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x17 children: not-inline
BlockContainer <div> at (8,8) content-size 784x17 children: inline
frag 0 from TextNode start: 1, length: 1, rect: [8,8 14.265625x17] baseline: 13.296875
BlockContainer <html> at (0,0) content-size 800x30 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x14 children: not-inline
BlockContainer <div> at (8,8) content-size 784x14 children: inline
frag 0 from TextNode start: 1, length: 1, rect: [8,8 11.59375x14] baseline: 10.890625
"A"
TextNode <#text>
BlockContainer <(anonymous)> at (8,25) content-size 784x0 children: inline
BlockContainer <(anonymous)> at (8,22) content-size 784x0 children: inline
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x33]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x17]
PaintableWithLines (BlockContainer<DIV>) [8,8 784x17]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x30]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x14]
PaintableWithLines (BlockContainer<DIV>) [8,8 784x14]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,25 784x0]
PaintableWithLines (BlockContainer(anonymous)) [8,22 784x0]

View file

@ -1,33 +1,33 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x67 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x51 children: not-inline
BlockContainer <div> at (8,8) content-size 100x51 children: inline
frag 0 from BlockContainer start: 0, length: 0, rect: [8,8 114.265625x17] baseline: 13.296875
frag 1 from BlockContainer start: 0, length: 0, rect: [8,25 123.609375x17] baseline: 13.296875
frag 2 from BlockContainer start: 0, length: 0, rect: [8,42 133.921875x17] baseline: 13.296875
BlockContainer <span> at (8,8) content-size 114.265625x17 inline-block [BFC] children: inline
frag 0 from TextNode start: 0, length: 2, rect: [8,8 114.265625x17] baseline: 13.296875
BlockContainer <html> at (0,0) content-size 800x58 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x42 children: not-inline
BlockContainer <div> at (8,8) content-size 100x42 children: inline
frag 0 from BlockContainer start: 0, length: 0, rect: [8,8 111.59375x14] baseline: 10.890625
frag 1 from BlockContainer start: 0, length: 0, rect: [8,22 119.1875x14] baseline: 10.890625
frag 2 from BlockContainer start: 0, length: 0, rect: [8,36 127.5625x14] baseline: 10.890625
BlockContainer <span> at (8,8) content-size 111.59375x14 inline-block [BFC] children: inline
frag 0 from TextNode start: 0, length: 2, rect: [8,8 111.59375x14] baseline: 10.890625
" A"
TextNode <#text>
BlockContainer <span> at (8,25) content-size 123.609375x17 inline-block [BFC] children: inline
frag 0 from TextNode start: 0, length: 3, rect: [8,25 123.609375x17] baseline: 13.296875
BlockContainer <span> at (8,22) content-size 119.1875x14 inline-block [BFC] children: inline
frag 0 from TextNode start: 0, length: 3, rect: [8,22 119.1875x14] baseline: 10.890625
" AB"
TextNode <#text>
BlockContainer <span> at (8,42) content-size 133.921875x17 inline-block [BFC] children: inline
frag 0 from TextNode start: 0, length: 4, rect: [8,42 133.921875x17] baseline: 13.296875
BlockContainer <span> at (8,36) content-size 127.5625x14 inline-block [BFC] children: inline
frag 0 from TextNode start: 0, length: 4, rect: [8,36 127.5625x14] baseline: 10.890625
" ABC"
TextNode <#text>
BlockContainer <(anonymous)> at (8,59) content-size 784x0 children: inline
BlockContainer <(anonymous)> at (8,50) content-size 784x0 children: inline
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x67]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x51]
PaintableWithLines (BlockContainer<DIV>) [8,8 100x51] overflow: [8,8 133.921875x51]
PaintableWithLines (BlockContainer<SPAN>) [8,8 114.265625x17]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x58]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x42]
PaintableWithLines (BlockContainer<DIV>) [8,8 100x42] overflow: [8,8 127.5625x42]
PaintableWithLines (BlockContainer<SPAN>) [8,8 111.59375x14]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<SPAN>) [8,25 123.609375x17]
PaintableWithLines (BlockContainer<SPAN>) [8,22 119.1875x14]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<SPAN>) [8,42 133.921875x17]
PaintableWithLines (BlockContainer<SPAN>) [8,36 127.5625x14]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,59 784x0]
PaintableWithLines (BlockContainer(anonymous)) [8,50 784x0]

View file

@ -1,16 +1,16 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x33 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x17 children: not-inline
BlockContainer <div> at (8,8) content-size 784x17 children: inline
frag 0 from TextNode start: 1, length: 1, rect: [8,8 14.265625x17] baseline: 13.296875
BlockContainer <html> at (0,0) content-size 800x30 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x14 children: not-inline
BlockContainer <div> at (8,8) content-size 784x14 children: inline
frag 0 from TextNode start: 1, length: 1, rect: [8,8 11.59375x14] baseline: 10.890625
"A"
TextNode <#text>
BlockContainer <(anonymous)> at (8,25) content-size 784x0 children: inline
BlockContainer <(anonymous)> at (8,22) content-size 784x0 children: inline
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x33]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x17]
PaintableWithLines (BlockContainer<DIV>) [8,8 784x17]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x30]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x14]
PaintableWithLines (BlockContainer<DIV>) [8,8 784x14]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,25 784x0]
PaintableWithLines (BlockContainer(anonymous)) [8,22 784x0]

View file

@ -1,26 +1,26 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x34 children: not-inline
BlockContainer <form#form> at (8,8) content-size 784x34 children: inline
frag 0 from BlockContainer start: 0, length: 0, rect: [11,11 194x28] baseline: 16.296875
BlockContainer <body> at (8,8) content-size 784x28 children: not-inline
BlockContainer <form#form> at (8,8) content-size 784x28 children: inline
frag 0 from BlockContainer start: 0, length: 0, rect: [11,11 154x22] baseline: 13.890625
TextNode <#text>
BlockContainer <textarea#textarea> at (11,11) content-size 194x28 inline-block [BFC] children: not-inline
BlockContainer <div> at (11,11) content-size 194x17 children: not-inline
BlockContainer <div> at (11,11) content-size 194x17 children: inline
frag 0 from TextNode start: 0, length: 14, rect: [11,11 108.453125x17] baseline: 13.296875
BlockContainer <textarea#textarea> at (11,11) content-size 154x22 inline-block [BFC] children: not-inline
BlockContainer <div> at (11,11) content-size 154x14 children: not-inline
BlockContainer <div> at (11,11) content-size 154x14 children: inline
frag 0 from TextNode start: 0, length: 14, rect: [11,11 88.109375x14] baseline: 10.890625
"Original value"
TextNode <#text>
TextNode <#text>
BlockContainer <(anonymous)> at (8,58) content-size 784x0 children: inline
BlockContainer <(anonymous)> at (8,52) content-size 784x0 children: inline
TextNode <#text>
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x34]
PaintableWithLines (BlockContainer<FORM>#form) [8,8 784x34]
PaintableWithLines (BlockContainer<TEXTAREA>#textarea) [8,8 200x34]
PaintableWithLines (BlockContainer<DIV>) [11,11 194x17]
PaintableWithLines (BlockContainer<DIV>) [11,11 194x17]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x28]
PaintableWithLines (BlockContainer<FORM>#form) [8,8 784x28]
PaintableWithLines (BlockContainer<TEXTAREA>#textarea) [8,8 160x28]
PaintableWithLines (BlockContainer<DIV>) [11,11 154x14]
PaintableWithLines (BlockContainer<DIV>) [11,11 154x14]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer(anonymous)) [8,58 784x0]
PaintableWithLines (BlockContainer(anonymous)) [8,52 784x0]

View file

@ -0,0 +1,7 @@
<!doctype html><style>
html { font-size: medium; }
body { font-size: 200%; }
main { font-size: 2em; }
article { font-family: monospace; }
div { }
</style><body>abc<main>def<article>ghi<div>jkl

View file

@ -1,2 +1,2 @@
Top: 16
Top: 13
Left: 8

View file

@ -135,7 +135,7 @@ grid-row-start: auto
grid-template-areas: none
grid-template-columns: auto
grid-template-rows: auto
height: 2329px
height: 1918px
inline-size: auto
inset-block-end: auto
inset-block-start: auto
@ -146,9 +146,9 @@ justify-content: normal
justify-items: legacy
justify-self: auto
left: auto
margin-block-end: 16px
margin-block-end: 13px
margin-block-start: 8px
margin-bottom: 16px
margin-bottom: 13px
margin-inline-end: 8px
margin-inline-start: 8px
margin-left: 8px