Commit graph

1020 commits

Author SHA1 Message Date
Shannon Booth
f890f289a7 LibWeb: Use resolved subgrid inline size for row contributions
Row subgrid contribution sizing reused the parent grid's available
width, so descendants in flexible columns could contribute an unwrapped
height and then wrap during layout.

Use the resolved subgrid item width when measuring row contributions.
2026-06-22 18:27:22 +02:00
Shannon Booth
870aaa8a1f LibWeb: Resolve subgrid inline sizing before row contributions
When collecting row-axis contributions from subgrid descendants,
resolve the subgrid column metrics first so intrinsic height measurement
uses the correct inline size. This prevents text from being measured as
if it had no usable width, which inflated auto row sizes.
2026-06-22 18:27:22 +02:00
Callum Law
2c6aa4d272 LibWeb: Apply null transform properties on style recomputation
When applying style in `Layout::Node::apply_style` we previously ignored
null `rotate`, `translate`, and `scale` values which left the old values
in place in the case of nonnull -> null changes.

Fixes #10125
2026-06-18 12:26:22 +02:00
Jelle Raaijmakers
d642f7d85a LibWeb: Do not dump number of children for StackingContexts
The number of children a SC has is not that useful in dumps, when all
its children are dumped anyway.
2026-06-18 10:50:08 +02:00
Jelle Raaijmakers
9ed75e4f50 LibWeb/CSS: Retain length precision in PercentageOr<T>
Instead of operating within the (saturating) CSSPixels constraints,
calculate the expected value using a floating point calculation first
and then create the CSSPixels value.
2026-06-18 09:59:41 +02:00
Tim Ledbetter
4ecfd0903f LibWeb: Allow transforms to apply to pseudo elements
Previously `is_transformable()` didn't take pseudo elements into
account.
2026-06-16 11:32:02 +02:00
Jelle Raaijmakers
cf3bb8c129 LibWeb: Distinguish first and last baseline sets in box_baseline()
box_baseline() applied CSS2's bottom margin edge rule for non-visible
overflow to every caller, so flex items with hidden overflow were
baseline-aligned by their margin edge instead of their text. CSS Align
scopes that rule to a box's last baseline set, while flex baseline
alignment and table cells use the first set, which always derives from
content. Parameterize box_baseline() on the requested baseline set and
propagate it through the recursive child lookup.
2026-06-16 10:39:02 +02:00
Shannon Booth
96aa4b3ad3 LibWeb: Only apply CSS transforms to transformable elements
Add Node::is_transformable() per the CSS Transforms spec and gate
transform handling on it, so non-replaced inline boxes are no longer
transformed.
2026-06-14 22:12:00 +02:00
Jelle Raaijmakers
e0ca142184 LibWeb: Prevent flex/grid margin collapsing with its contents 2026-06-10 13:11:47 +02:00
Andreas Kling
9340d2d1a3 LibWeb: Make layout nodes refcounted
Move the layout tree from GC allocation to refcounted ownership so
removed layout and paint subtrees are destroyed synchronously instead
of waiting for the next GC sweep. This dramatically reduces GC memory
usage peaks after layout tree churn and makes it easier for memory use
to fall back after large document updates.

Update layout factories, tree traversal, SVG layout node creation,
paintable back-pointers, and pseudo-element layout links to use RefPtr
ownership.

Make display: contents follow the same shape as Blink and WebKit: the
element itself does not create a layout node, and its children are
flattened into the nearest layout parent. Wrap direct non-whitespace
text in an anonymous inline node when the boxless element contributes
inherited style to that text.

Use an internal inline wrapper for display: contents pseudo-elements
so generated content can still participate in layout, painting, hit
testing, and pseudo-element queries. Keep CSSOM reporting the computed
display value from the pseudo style, not the internal wrapper.

Remove the retained out-of-tree layout node list and its testing hook,
since the flattened model does not need a side owner for boxless
elements. Add coverage for inherited text style, dynamic insertion
order, pseudo-element hit testing, and computed style queries.
2026-06-07 20:52:49 +02:00
Andreas Kling
9c040f1dd3 LibWeb: Make generated content text layout-owned
Stop creating unattached DOM Text nodes for string items in generated
CSS content. These text nodes are layout artifacts, so store their text
directly in a GeneratedTextNode instead of pretending they have DOM
backing.

Teach text shaping and first-letter splitting to read text through the
layout text source while keeping DOM-specific behavior behind an
optional DOM text accessor. This preserves generated first-letter
handling without rooting fake DOM nodes.

Add crash coverage for generated content surviving GC and rebaseline
layout dumps that now identify generated text explicitly.
2026-06-07 20:52:49 +02:00
Zaggy1024
e6664213ac LibWeb: Fall back to TextInputBox for unsupported input types
This isn't strictly correct as it stands currently, since the size
attribute isn't supposed to affect type="time" and others, but those
types currently end up with zero width instead.

Size could probably be applied through shadow DOM style, and the input
layout box would simply allow content sizing.
2026-06-05 12:49:24 +02:00
Zaggy1024
2b6ebe9738 Tests: Add a layout test for input[type="time"] without width
When width is unspecified, this input type has no actual width.
2026-06-05 12:49:24 +02:00
sideshowbarker
4df6ecd176 LibWeb: Ignore vertical-align on flex and grid items in box_baseline
Problem: Borked layout on (flex-styled) “D&D Beyond” site.

Cause: FormattingContext::box_baseline() was applying the box’s
vertical-align unconditionally. But vertical-align shouldn’t be
consulted for flex items or grid items.

Fix: Skip vertical-align handling in box_baseline() when the box is a
flex or grid item.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/9840
2026-06-05 10:11:06 +01:00
Tim Ledbetter
709c10f8ec LibWeb: Let range inputs stretch in grid containers
Previously, the UA stylesheet gave range inputs a definite
`width: 20ch`. This prevented range inputs from filling their grid
track. We now source the default width and height from a new
`RangeInputBox` type. This approach matches the implementation of other
input types.
2026-05-30 12:17:58 +01:00
Zaggy1024
8a85cafd36 LibWeb: Move media controls' timeline fill to an inner div
This will allow us to contain the buffered ranges within the timeline's
area.
2026-05-28 10:30:20 -05:00
Tim Ledbetter
8039419775 LibWeb: Account for floats when computing IFC abspos static position
Previously, when no previous sibling has a line box fragment, the
static position for inline-level elements defaulted to (0, 0), ignoring
float intrusion into the line box. We now use
`leftmost_inline_offset_at()` so the hypothetical box is placed on the
float-shortened line.
2026-05-28 10:40:21 +02:00
Andreas Kling
ece9e39270 LibWeb: Inherit grid area line names into subgrids
Subgrids already inherited explicitly named parent grid lines, but not
the implicit line names from named grid areas. Discord places its server
rail and channel list through nested subgrids using those area names, so
the inner subgrid resolved both children against the wrong columns.

Collect the parent's implicit area boundary names, clamp each
overlapping area to the subgrid span, and assign the corresponding
implicit start and end line names on the subgrid. This follows CSS Grid
2's subgrid area inheritance text and lets the inherited names pass
through nested subgrids.

Add a layout test that mirrors the Discord nesting shape and covers
placing items by inherited parent area names through another subgrid.
2026-05-25 22:00:50 +02:00
Andreas Kling
a998534264 LibWeb: Add CSS grid subgrid layout support
Use parent grid tracks for subgridded axes, inherit parent line names,
clamp item placement to the subgrid explicit grid, and expose subgrid
children as parent track sizing contributors instead of sizing the
subgrid box itself.

Handle automatic subgrid spans, subgrid gap differences, edge
margin/border/padding contributions, non-applicable subgrid used values,
and row-subgrid auto-placement bounds.

Add focused layout and text coverage for inherited names, parent track
sizing, clamped placement, auto-fill line names, automatic spans,
gutters, and edge space. The text expectations were matched against
Chromium.
2026-05-25 18:11:38 +02:00
Martin Chrástek
a404efa999 Tests: Add explicit UTF-8 charset declarations to existing tests 2026-05-23 11:57:33 +02:00
Andreas Kling
d98cea80e2 LibWeb: Let IFC publish inline-end static position
Store the static-position insertion point produced by an inline
formatting context and let block layout consume it for originally-inline
absolute boxes that follow an anonymous inline wrapper. This removes the
block formatting context's fragment-walking reconstruction of the same
position.

Keep the calculation in IFC aware of forced breaks, aligned inline
content, trailing inline margins, wrapped lines, RTL inline content, and
vertical writing modes.

Keep regression coverage for the static-position cases covered while
building this model.
2026-05-23 11:01:58 +02:00
Andreas Kling
d05b30a8dc LibWeb: Preserve inline-flex strut descent
When an inline flex fragment raises the line box baseline, include the
parent strut descent in the line box bottom and advance the next line
from that enlarged line box. This keeps following wrapped or broken
lines from overlapping the extra descent.

Add ref and text coverage for inline-flex line height and line
advancement.
2026-05-23 11:01:58 +02:00
Callum Law
a6f24e91cc LibWeb: Simplify is_definite_size 2026-05-20 09:47:17 +01:00
Andreas Kling
a104226d3c LibWeb: Cover table wrappers in grid layout
Add layout and text coverage for display:table grid items whose
anonymous wrappers are sized and aligned by grid layout. Cover partial
grid areas, percentage table widths and margins, auto margins,
oversized alignment, stretched wrappers, intrinsic tracks, distributed
track spacing, percentage min/max widths, border-box constraints, and
intrinsic max-width constraints.
2026-05-19 10:41:52 +02:00
Andreas Kling
4cdad196ed LibWeb: Resolve table wrappers from grid areas
Measure anonymous table wrapper grid items against their grid-area
containing block instead of the layout-tree containing block. Recompute
the wrapper width after track spacing and store the grid-area size so
table layout resolves table-root percentages against the same basis.
2026-05-19 10:41:52 +02:00
Andreas Kling
a0ba84975b LibWeb: Treat cyclic grid percentages as auto
Treat non-replaced grid item percentage preferred sizes as auto when
computing intrinsic grid track contributions. This matches the CSS
Sizing cyclic percentage contribution rule and avoids inflating auto
rows before the final grid area size is known.

Keep resolving those percentages during final item layout. Update the
new layout tests to cover row inflation and nested overlap.
2026-05-18 08:20:28 +02:00
Andreas Kling
7a53c854e6 LibWeb: Add grid percentage height contribution tests
Add coverage for percentage-height grid items contributing to row
track sizing. These cases mirror nested homepage grids where auto rows
are sized from grid items whose own height is percentage-based.
2026-05-18 08:20:28 +02:00
Andreas Kling
6fcdd74b38 LibWeb: Resolve SVG max-content width from CSS height
When a replaced element has no natural width or height but has a
preferred aspect ratio, max-content width fell through to the CSS
Sizing fallback that uses the initial containing block width.

Use a definite used height to derive max-content width through the
aspect ratio before the fallback. Keep the existing natural-height SVG
path first by only doing this for elements without natural height. Add
a focused layout test for the nested flex item case.
2026-05-17 15:20:36 +02:00
Shannon Booth
7afb4ca328 LibWeb: Place single-line flex lines at cross-start
For single-line flex containers, the flex line should not be centered in
the container’s cross axis. Instead, it should be placed at cross-start.
2026-05-17 10:15:38 +02:00
Shannon Booth
825a37cc8e LibWeb: Keep intrinsic heights indefinite for percentage children
A used height computed from an intrinsic sizing keyword like fit-content
does not necessarily establish a definite containing-block height for
percentage descendants.

Preserve indefinite percentage-height resolution both in normal block
layout and in absolutely positioned/fixed layout, including cases where
non-auto top/bottom insets resolve the box’s own used height.

Add regressions for a regular fit-content block container and fixed
fit-content containers with min-height and top/bottom insets.
2026-05-16 17:06:03 +02:00
Shannon Booth
cb1b5aa46b LibWeb: Account for SVG partial intrinsic size in max-content sizing
When an outer <svg> has a viewBox and only one sizing attribute, SVG
Integration keeps the missing dimension as auto while exposing the
specified dimension and intrinsic aspect ratio to CSS sizing.

Teach replaced max-content sizing to resolve that SVG-specific partial
intrinsic size through CSS2 replaced sizing before falling back to the
CSS Sizing rules for replaced elements without natural sizes. This keeps
the generic fallback path intact while avoiding viewport-sized
max-content contributions for SVGs such as height+viewBox logos.

In combination with the previous commit, fixes the layout of logos
on polar.sh
2026-05-16 17:05:01 +02:00
Shannon Booth
296b561b98 LibWeb: Handle replaced min/max-content sizes without natural dimensions
CSS Sizing defines the max-content size of a replaced element without
natural dimensions in terms of the size it would have as a float with an
auto preferred size.

Change max-content width/height calculation to use those fallback rules
for replaced elements that lack a natural size in the queried axis.

Reduced from bad layout of the logo section on polar.sh
2026-05-16 17:05:01 +02:00
Pavel Shliak
166c02089d LibWeb: Preserve column indices across colgroups
Keep the collected column index across table-column-group siblings, so
columns in later colgroups are not recorded as column 0.
2026-05-14 12:41:54 +01:00
Jelle Raaijmakers
7f0ae9bd4c LibWeb: Derive inline flex/grid baselines from the first child line
When an inline flex/grid container has no line boxes of its own, we
derive its baseline from a child box. The generic recursive path can
then use the child's last wrapped line, even though the flex/grid
baseline should come from the child item's alignment baseline.

Use the selected child's first line box directly for inline flex/grid
containers, avoiding an incorrect baseline when that child wraps.
2026-04-30 17:34:25 +02:00
Psychpsyo
d74aa418f7 LibWeb: Position list marker to the right of right-to-left text 2026-04-30 16:20:10 +02:00
Sam Atkins
73c4b77f68 LibWeb/HTML: Support align attributes on table sections and rows
thead, tbody, tfoot, tr, td, and th all have an `align` presentational
attribute with identical definitions. We previously only supported it
for td and th, and also allowed arbitrary text-align values instead of
the 4 dictated by the spec.
2026-04-30 15:20:22 +02:00
Johan Dahlin
f7499105dd LibWeb: Implement inline PDF viewing using the bundled pdf.js viewer 2026-04-30 07:46:12 +02:00
Jelle Raaijmakers
1aeb080250 LibCompress: Treat LZW decoding errors as end of stream
The LZW data for both GIF and TIFF images is sometimes intentionally
missing an end-of-information (EOI) code, which technically is a
decoding error, but in practive is handled gracefully by Firefox, Safari
and Chrome for GIFs and Safari for TIFFs. Let's mirror their behavior.

The included WPT test exposes the fact that trailing garbage bytes can
also result in decoding errors. We handle this in the LZW logic rather
than in the image decoding since our LZW implementation is currently
only used by GIF and TIFF decoding. The error is logged behind the
LZW_DEBUG flag.
2026-04-29 20:28:15 +02:00
Andreas Kling
d1d739b533 LibWeb: Clear stale layout descendants for skipped subtrees
When content-visibility:hidden starts skipping a subtree, clear the
stale layout and paint nodes for its descendants.

Preserve SVG mask, clipPath, and pattern resource boxes only when
they are attached to a referencing layout subtree outside the subtree
being hidden. Resources used inside the hidden subtree are cleared
with that subtree, so they rebuild under the live referencing layout
node when the subtree becomes visible again.

Otherwise observed descendants can keep old paintables around after
the current paint tree has been rebuilt without them.
2026-04-27 16:22:11 +02:00
Aliaksandr Kalenik
cd6672eee0 LibWeb: Fix min-content collapsing to 0 with min-width: 0 descendant
During intrinsic sizing, compute_width() ran on block descendants with
an intrinsic-sizing available space. For a non-FC-establishing block
with auto width, used_width stayed auto, and the min-width clamp then
compared AvailableSize::min-content against min-width via operator<,
which always returns true when the left side is min-content. The clamp
fired with min-width: 0 and set content_width to 0 permanently.

Skip the min-width clamp when used_width is still auto, mirroring the
max-width clamp a few lines above which already no-ops via
to_px_or_zero. The real width is then set by the IntrinsicSizing branch
in layout_block_level_children.
2026-04-24 19:08:28 +02:00
Shannon Booth
b0acc18f9b LibWeb: Clamp limited grid item contributions by fixed max tracks
When resolving grid track sizes, limited min/max-content contributions
should be capped by fixed max track sizing functions, including the
argument to fit-content(). We were instead falling back to the grid
container maximum size, which allowed a grid item with overflowing
contents in a fit-content(0) row to inflate the intrinsic block size of
a nested grid.

That bogus intrinsic height could then be used for the grid's second row
sizing pass, causing unrelated flexible rows to absorb the extra space.
2026-04-23 09:23:02 +01:00
Tim Ledbetter
d8825c89af LibWeb: Use caption content width for inline layout in table captions
Previously, `run_caption_layout()` passed the table's border-box width
as the available space to the caption's formatting context. The BFC then
used this width directly for inline line breaking, causing text to
overflow the caption's content box by the size of the caption's own
border and padding.
2026-04-22 15:35:07 +01:00
Tim Ledbetter
da5e002db1 LibWeb: Keep select button text in sync with the selected option
Previously, the select button's text was only refreshed inside the
two non-trivial branches of the selectedness setting algorithm.
Paths that left the select with exactly one selected option hit a
no-op branch and skipped the refresh.

Fix this by implementing the "clone selected option into select
button" algorithm and invoking it whenever the set of selected options
may have changed.
2026-04-22 09:15:29 -04:00
Shannon Booth
4a460b1dda LibWeb: Apply calculated vertical-align offsets in LineBuilder
Fixes the alignment of the arrow for "Get in touch" on canonical.com
2026-04-15 21:49:40 +02:00
Shannon Booth
482e5e770f LibWeb: Let flexbox stretch auto-width text inputs
Don't rewrite text input 'width: auto' to 'size()ch' in
'HTMLInputElement::adjust_computed_style()'. That turns the control into
a definite-width flex item and prevents 'align-items: stretch' from
expanding it across the flex container.

Fixes the layout of the input element on the element matrix login page.
2026-04-13 09:57:01 +02:00
Callum Law
919dba87b9 LibWeb: Support calculated <flex> values
This spec note reads to me as explicitly disallowing combining
`<length>` and `<flex>` (i.e. `calc(1px + 1fr)`). This behavior is
already implemented (as it is for all other combination of units i.e.
`<length>` and `<time>`).
2026-04-09 21:41:49 +01:00
Shannon Booth
af03e07f90 LibWeb: Clamp replaced element min/max sizes in the content box space
The replaced element sizing code was comparing tentative used sizes
min-width/min-height and max-width/max-height. For box-sizing:
border-box, that mixes content-box and border-box measurements, which
can clamp replaced-like elements incorrectly.

This could make, for example search/text inputs with explicit height
and padding render too short.

Resolve min/max constraints with calculate_inner_width() and
calculate_inner_height() before clamping so the comparison uses
the same inner sizing space as the tentative replaced size.

Fixes the sizing of the search bar on:

https://tv.apple.com/se
2026-04-06 12:35:12 +02:00
Andreas Kling
e2e3c7fcdf LibWeb: Rebuild counter style cache lazily
Stop rebuilding the counter style cache from every style update.
That made unrelated restyles pay the full counter-style cost even when
no relevant stylesheet state had changed.

Dirty the cache when stylesheet rule caches are invalidated and rebuild
it on the first counter-style lookup instead. Also make cold cache
rebuilds include user stylesheets.

Add regression tests covering insertRule() and replaceSync() updates
that should make newly defined counter styles take effect.
2026-04-05 12:34:28 +02:00
Andreas Kling
1bfcf49ffe LibWeb: Honor reversed axes for flex overflow
Scrollable overflow still assumed a top-left scroll origin and only
added trailing padding on the physical bottom edge. That broke
scrollWidth and scrollHeight for flex containers whose main or cross
axis was reversed by writing-mode, direction, flex-direction, or
wrap-reverse.

Teach flex layout to place wrapped lines using the computed cross-axis
direction and to measure scrollable overflow from the container's
actual scroll origin so reachable reversed overflow is preserved, the
unreachable side is clipped, and end padding is added on the correct
physical edge.

Keep per-item cross-axis placement using the existing behavior.
Applying full cross-axis reversal there regressed baseline alignment
tests, and zero-sized boxes exactly at the scroll origin must still
contribute descendant overflow, so the unreachable-overflow checks
need strict comparisons.

This makes negative-overflow-002 and negative-overflow-003 pass and
improves negative-overflow, align-content-wrap-003, and
overflow-with-padding.
2026-04-05 10:42:32 +02:00
Tim Ledbetter
d9079d2078 LibWeb: Apply z-index only to positioned elements
`z-index` values other than `auto` also apply to grid and flex items
because they behave as if their `position` were `relative`.
2026-04-03 23:28:39 +02:00